//
//  This file is part of a reduced file concatenation of the CwlViews
//  framework with internal interfaces for source inclusion in projects instead
//  of library inclusion.
//  For details, visit: https://github.com/mattgallagher/CwlViews
//
//  Copyright © 2015-2018 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
//
//  Permission to use, copy, modify, and/or distribute this software for any
//  purpose with or without fee is hereby granted, provided that the above
//  copyright notice and this permission notice appear in all copies.
//
//  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
//  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
//  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
//  SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
//  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
//  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
//  IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
//  This file was generated by the CwlUtilsConcat tool on 2018-04-02 04:01:18 +0000 from the following files:
//
//    TableView.swift
//    Application.swift
//    ViewController.swift
//    ScrollView.swift
//

#if os(macOS)
	import AppKit
#else
	import UIKit
#endif

// MARK: ### CwlTableView.swift ###

class TableView<RowData>: ConstructingBinder, TableViewConvertible {
	typealias Instance = UITableView
	typealias Inherited = ScrollView
	
	var state: ConstructingBinderState<Instance, Binding>
	required init(state: ConstructingBinderState<Instance, Binding>) {
		self.state = state
	}
	static func bindingToInherited(_ binding: Binding) -> Inherited.Binding? {
		if case .inheritedBinding(let s) = binding { return s } else { return nil }
	}
	var uiTableView: Instance { return instance() }

	enum Binding: TableViewBinding {
		typealias RowDataType = RowData
		typealias EnclosingBinder = TableView
		static func tableViewBinding(_ binding: Binding) -> Binding { return binding }
		case inheritedBinding(Inherited.Binding)
		
		//	0. Static bindings are applied at construction and are subsequently immutable.
		case tableViewStyle(StaticValue<UITableViewStyle>)

		//	1. Value bindings may be applied at construction and may subsequently change.
		case allowsMultipleSelection(DynamicValue<Bool>)
		case allowsMultipleSelectionDuringEditing(DynamicValue<Bool>)
		case allowsSelection(DynamicValue<Bool>)
		case allowsSelectionDuringEditing(DynamicValue<Bool>)
		case backgroundView(DynamicValue<ViewConvertible?>)
		case cellLayoutMarginsFollowReadableWidth(DynamicValue<Bool>)
		case isEditing(Signal<SetOrAnimate<Bool>>)
		case estimatedRowHeight(DynamicValue<CGFloat>)
		case estimatedSectionFooterHeight(DynamicValue<CGFloat>)
		case estimatedSectionHeaderHeight(DynamicValue<CGFloat>)
		case remembersLastFocusedIndexPath(DynamicValue<Bool>)
		case rowHeight(DynamicValue<CGFloat>)
		case sectionFooterHeight(DynamicValue<CGFloat>)
		case sectionHeaderHeight(DynamicValue<CGFloat>)
		case sectionIndexBackgroundColor(DynamicValue<UIColor?>)
		case sectionIndexColor(DynamicValue<UIColor?>)
		case sectionIndexMinimumDisplayRowCount(DynamicValue<Int>)
		case sectionIndexTrackingBackgroundColor(DynamicValue<UIColor?>)
		case sectionIndexTitles(DynamicValue<[String]?>)
		case separatorColor(DynamicValue<UIColor?>)
		case separatorEffect(DynamicValue<UIVisualEffect?>)
		case separatorInset(DynamicValue<UIEdgeInsets>)
		case separatorStyle(DynamicValue<UITableViewCellSeparatorStyle>)
		case tableFooterView(DynamicValue<ViewConvertible?>)
		case tableHeaderView(DynamicValue<ViewConvertible?>)
		case tableData(DynamicValue<TableData<RowData>>)
		
		//	2. Signal bindings are performed on the object after construction.
		case deselectRow(Signal<SetOrAnimate<IndexPath>>)
		case scrollToNearestSelectedRow(Signal<SetOrAnimate<UITableViewScrollPosition>>)
		case scrollToRow(Signal<SetOrAnimate<TableScrollPosition>>)
		case selectRow(Signal<SetOrAnimate<TableScrollPosition?>>)
		
		//	3. Action bindings are triggered by the object after construction.
		case userDidScrollToRow(SignalInput<TableRow<RowData>>)
		case accessoryButtonTapped(SignalInput<TableRow<RowData>>)
		case didDeselectRow(SignalInput<TableRow<RowData>>)
		case didEndDisplayingFooter(SignalInput<Int>)
		case didEndDisplayingHeader(SignalInput<Int>)
		case didEndDisplayingRow(SignalInput<TableRow<RowData>>)
		case didEndEditingRow(SignalInput<TableRow<RowData>?>)
		case didHightlightRow(SignalInput<TableRow<RowData>>)
		case didSelectRow(SignalInput<TableRow<RowData>>)
		case didUnhighlightRow(SignalInput<TableRow<RowData>>)
		case moveRow(SignalInput<(from: TableRow<RowData>, to: IndexPath)>)
		case selectionDidChange(SignalInput<[TableRow<RowData>]?>)
		case visibleRowsChanged(SignalInput<[TableRow<RowData>]>)
		case commit(SignalInput<(editingStyle: UITableViewCellEditingStyle, row: TableRow<RowData>)>)
		
		//	4. Delegate bindings require synchronous evaluation within the object's context.
		case cellIdentifier((TableRow<RowData>) -> String?)
		case canEditRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case canFocusRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case canMoveRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case canPerformAction((_ action: Selector, _ tableRowData: TableRow<RowData>, _ sender: Any?) -> Bool)
		case cellConstructor((_ identifier: String?, _ rowSignal: SignalMulti<RowData>) -> TableViewCellConvertible)
		case dataMissingCell((IndexPath) -> TableViewCellConvertible)
		case didUpdateFocus((UITableView, UITableViewFocusUpdateContext, UIFocusAnimationCoordinator) -> Void)
		case editActionsForRow((_ tableRowData: TableRow<RowData>) -> [UITableViewRowAction]?)
		case editingStyleForRow((_ tableRowData: TableRow<RowData>) -> UITableViewCellEditingStyle)
		case estimatedHeightForFooter((_ section: Int) -> CGFloat)
		case estimatedHeightForHeader((_ section: Int) -> CGFloat)
		case estimatedHeightForRow((_ tableRowData: TableRow<RowData>) -> CGFloat)
		case footerHeight((_ section: Int) -> CGFloat)
		case footerView((_ section: Int, _ title: String?) -> ViewConvertible?)
		case headerHeight((_ section: Int) -> CGFloat)
		case headerView((_ section: Int, _ title: String?) -> ViewConvertible?)
		case heightForRow((_ tableRowData: TableRow<RowData>) -> CGFloat)
		case indentationLevelForRow((_ tableRowData: TableRow<RowData>) -> Int)
		case indexPathForPreferredFocusedView((UITableView) -> IndexPath)
		case shouldHighlightRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case shouldIndentWhileEditingRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case shouldShowMenuForRow((_ tableRowData: TableRow<RowData>) -> Bool)
		case shouldUpdateFocus((UITableView, UITableViewFocusUpdateContext) -> Bool)
		case targetIndexPathForMoveFromRow((_ tableView: UITableView, _ sourceIndexPath: IndexPath, _ proposedIndexPath: IndexPath) -> IndexPath)
		case titleForDeleteConfirmationButtonForRow((_ tableRowData: TableRow<RowData>) -> String?)
		case willBeginEditingRow((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> Void)
		case willDeselectRow((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> IndexPath?)
		case willDisplayFooter((_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void)
		case willDisplayHeader((_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void)
		case willDisplayRow((_ tableView: UITableView, _ tableRowData: TableRow<RowData>, _ cell: UITableViewCell) -> Void)
		case willSelectRow((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> IndexPath?)
	}

	struct Preparer: ConstructingPreparer {
		typealias EnclosingBinder = TableView
		var linkedPreparer = Inherited.Preparer()
		
		func constructStorage() -> EnclosingBinder.Storage { return Storage(cellIdentifier: cellIdentifier) }
		func constructInstance(subclass: EnclosingBinder.Instance.Type) -> EnclosingBinder.Instance {
			return subclass.init(frame: CGRect.zero, style: tableViewStyle)
		}
		
		// Actual delegate construction is handled by the scroll view preparer
		init() {
			self.init(delegateClass: Delegate.self)
		}
		init(delegateClass: Delegate.Type) {
			linkedPreparer = Inherited.Preparer(delegateClass: delegateClass)
		}
		var possibleDelegate: Delegate? { return linkedPreparer.possibleDelegate as? Delegate }
		mutating func delegate() -> Delegate { return linkedPreparer.delegate() as! Delegate }
		
		var tableViewStyle: UITableViewStyle = .plain
		var rowsChangedInput: SignalInput<[TableRow<RowData>]>? = nil
		var cellIdentifier: (TableRow<RowData>) -> String? = { _ in nil }
		
		mutating func prepareBinding(_ binding: Binding) {
			switch binding {
			case .cellIdentifier(let x): cellIdentifier = x
			case .tableViewStyle(let x): tableViewStyle = x.value
			case .userDidScrollToRow(let x):
				let s1 = #selector(UIScrollViewDelegate.scrollViewDidScrollToTop(_:))
				let s2 = #selector(UIScrollViewDelegate.scrollViewDidEndDragging(_:willDecelerate:))
				let s3 = #selector(UIScrollViewDelegate.scrollViewDidEndDecelerating(_:))
				delegate().addSelector(s1).userDidScrollToRow = x
				_ = delegate().addSelector(s2)
				_ = delegate().addSelector(s3)
			case .accessoryButtonTapped(let x):
				let s = #selector(UITableViewDelegate.tableView(_:accessoryButtonTappedForRowWith:))
				delegate().addSelector(s).accessoryButtonTapped = x
			case .canEditRow(let x):
				let s = #selector(UITableViewDataSource.tableView(_:canEditRowAt:))
				delegate().addSelector(s).canEditRow = x
			case .canFocusRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:canFocusRowAt:))
				delegate().addSelector(s).canFocusRow = x
			case .canMoveRow(let x):
				let s = #selector(UITableViewDataSource.tableView(_:canMoveRowAt:))
				delegate().addSelector(s).canMoveRow = x
			case .canPerformAction(let x):
				let s = #selector(UITableViewDelegate.tableView(_:canPerformAction:forRowAt:withSender:))
				delegate().addSelector(s).canPerformAction = x
			case .didDeselectRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didDeselectRowAt:))
				delegate().addSelector(s).didDeselectRow = x
			case .didEndDisplayingFooter(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didEndDisplayingFooterView:forSection:))
				delegate().addSelector(s).didEndDisplayingFooter = x
			case .didEndDisplayingHeader(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didEndDisplayingHeaderView:forSection:))
				delegate().addSelector(s).didEndDisplayingHeader = x
			case .didEndDisplayingRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didEndDisplaying:forRowAt:))
				delegate().addSelector(s).didEndDisplayingRow = x
			case .didEndEditingRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didEndEditingRowAt:))
				delegate().addSelector(s).didEndEditingRow = x
			case .didHightlightRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didHighlightRowAt:))
				delegate().addSelector(s).didHightlightRow = x
			case .commit(let x):
				let s = #selector(UITableViewDataSource.tableView(_:commit:forRowAt:))
				delegate().addSelector(s).commit = x
			case .didSelectRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didSelectRowAt:))
				delegate().addSelector(s).didSelectRow = x
			case .didUnhighlightRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didUnhighlightRowAt:))
				delegate().addSelector(s).didUnhighlightRow = x
			case .didUpdateFocus(let x):
				let s = #selector(UITableViewDelegate.tableView(_:didUpdateFocusIn:with:))
				delegate().addSelector(s).didUpdateFocus = x
			case .editActionsForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:editActionsForRowAt:))
				delegate().addSelector(s).editActionsForRow = x
			case .editingStyleForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:editingStyleForRowAt:))
				delegate().addSelector(s).editingStyleForRow = x
			case .estimatedHeightForFooter(let x):
				let s = #selector(UITableViewDelegate.tableView(_:estimatedHeightForFooterInSection:))
				delegate().addSelector(s).estimatedHeightForFooter = x
			case .estimatedHeightForHeader(let x):
				let s = #selector(UITableViewDelegate.tableView(_:estimatedHeightForHeaderInSection:))
				delegate().addSelector(s).estimatedHeightForHeader = x
			case .estimatedHeightForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:estimatedHeightForRowAt:))
				delegate().addSelector(s).estimatedHeightForRow = x
			case .footerHeight(let x):
				let s = #selector(UITableViewDelegate.tableView(_:heightForFooterInSection:))
				delegate().addSelector(s).footerHeight = x
			case .footerView(let x):
				let s = #selector(UITableViewDelegate.tableView(_:viewForFooterInSection:))
				delegate().addSelector(s).footerView = x
			case .headerHeight(let x):
				let s = #selector(UITableViewDelegate.tableView(_:heightForHeaderInSection:))
				delegate().addSelector(s).headerHeight = x
			case .headerView(let x):
				let s = #selector(UITableViewDelegate.tableView(_:viewForHeaderInSection:))
				delegate().addSelector(s).headerView = x
			case .heightForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:heightForRowAt:))
				delegate().addSelector(s).heightForRow = x
			case .indentationLevelForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:indentationLevelForRowAt:))
				delegate().addSelector(s).indentationLevelForRow = x
			case .indexPathForPreferredFocusedView(let x):
				let s = #selector(UITableViewDelegate.indexPathForPreferredFocusedView(in:))
				delegate().addSelector(s).indexPathForPreferred = x
			case .moveRow(let x):
				let s = #selector(UITableViewDataSource.tableView(_:moveRowAt:to:))
				delegate().addSelector(s).moveRow = x
			case .shouldHighlightRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:shouldHighlightRowAt:))
				delegate().addSelector(s).shouldHighlightRow = x
			case .shouldIndentWhileEditingRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:shouldIndentWhileEditingRowAt:))
				delegate().addSelector(s).shouldIndentWhileEditingRow = x
			case .shouldShowMenuForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:shouldShowMenuForRowAt:))
				delegate().addSelector(s).shouldShowMenuForRow = x
			case .shouldUpdateFocus(let x):
				let s = #selector(UITableViewDelegate.tableView(_:shouldUpdateFocusIn:))
				delegate().addSelector(s).shouldUpdateFocus = x
			case .targetIndexPathForMoveFromRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:targetIndexPathForMoveFromRowAt:toProposedIndexPath:))
				delegate().addSelector(s).targetIndexPathForMoveFromRow = x
			case .titleForDeleteConfirmationButtonForRow(let x):
				let s = #selector(UITableViewDelegate.tableView(_:titleForDeleteConfirmationButtonForRowAt:))
				delegate().addSelector(s).titleForDeleteConfirmationButtonForRow = x
			case .visibleRowsChanged(let x):
				let s1 = #selector(UITableViewDelegate.tableView(_:willDisplay:forRowAt:))
				let s2 = #selector(UITableViewDelegate.tableView(_:didEndDisplaying:forRowAt:))
				delegate().addSelector(s1)
				delegate().addSelector(s2)
				rowsChangedInput = x
			case .inheritedBinding(let x): linkedPreparer.prepareBinding(x)
			default: break
			}
		}
		
		func applyBinding(_ binding: Binding, instance: Instance, storage: Storage) -> Cancellable? {
			switch binding {
			case .cellIdentifier: return nil
			case .tableViewStyle: return nil
			case .allowsMultipleSelection(let x): return x.apply(instance, storage) { i, s, v in i.allowsMultipleSelection = v }
			case .allowsMultipleSelectionDuringEditing(let x): return x.apply(instance, storage) { i, s, v in i.allowsMultipleSelectionDuringEditing = v }
			case .allowsSelection(let x): return x.apply(instance, storage) { i, s, v in i.allowsSelection = v }
			case .allowsSelectionDuringEditing(let x): return x.apply(instance, storage) { i, s, v in i.allowsSelectionDuringEditing = v }
			case .backgroundView(let x): return x.apply(instance, storage) { i, s, v in i.backgroundView = v?.uiView }
			case .cellLayoutMarginsFollowReadableWidth(let x): return x.apply(instance, storage) { i, s, v in i.cellLayoutMarginsFollowReadableWidth = v }
			case .deselectRow(let x): return x.apply(instance, storage) { i, s, v in i.deselectRow(at: v.value, animated: v.isAnimated) }
			case .isEditing(let x): return x.apply(instance, storage) { i, s, v in i.setEditing(v.value, animated: v.isAnimated) }
			case .estimatedRowHeight(let x): return x.apply(instance, storage) { i, s, v in i.estimatedRowHeight = v }
			case .estimatedSectionFooterHeight(let x): return x.apply(instance, storage) { i, s, v in i.estimatedSectionFooterHeight = v }
			case .estimatedSectionHeaderHeight(let x): return x.apply(instance, storage) { i, s, v in i.estimatedSectionHeaderHeight = v }
			case .remembersLastFocusedIndexPath(let x): return x.apply(instance, storage) { i, s, v in i.remembersLastFocusedIndexPath = v }
			case .rowHeight(let x): return x.apply(instance, storage) { i, s, v in i.rowHeight = v }
			case .scrollToNearestSelectedRow(let x): return x.apply(instance, storage) { i, s, v in i.scrollToNearestSelectedRow(at: v.value, animated: v.isAnimated) }
			case .scrollToRow(let x):
				// You can't scroll a table view until *after* the number of sections and rows has been read from the data source.
				// This occurs on didAddToWindow but the easiest way to track it is by waiting for the contentSize to be set (which is set for the first time immediately after the row count is read). This makes assumptions about internal logic of UITableView – if this logic changes in future, scrolls set on load might be lost (not a catastrophic problem).
				// Capture the scroll signal to stall it
				let capture = x.capture()
				
				// Create a signal pair that will join the capture to the destination *after* the first `contentSize` change is observed
				let pair = Signal<SetOrAnimate<TableScrollPosition>>.create()
				var kvo: NSKeyValueObservation? = instance.observe(\.contentSize) { (i, change) in
					_ = try? capture.bind(to: pair.input, resend: true)
				}
				
				// Use the output of the pair to apply the effects as normal
				return pair.signal.apply(instance, storage) { i, s, v in
					// Remove the key value observing after the first value is received.
					if let k = kvo {
						k.invalidate()
						kvo = nil
					}
					
					// Clamp to the number of actual sections and rows
					var indexPath = v.value.indexPath
					if indexPath.section >= i.numberOfSections {
						indexPath.section = i.numberOfSections - 1
					}
					if indexPath.section < 0 {
						return
					}
					if indexPath.row >= i.numberOfRows(inSection: indexPath.section) {
						indexPath.row = i.numberOfRows(inSection: indexPath.section) - 1
					}
					if indexPath.row < 0 {
						return
					}
					
					// Finally, perform the scroll
					i.scrollToRow(at: indexPath, at: v.value.position, animated: v.isAnimated)
				}
			case .sectionFooterHeight(let x): return x.apply(instance, storage) { i, s, v in i.sectionFooterHeight = v }
			case .sectionHeaderHeight(let x): return x.apply(instance, storage) { i, s, v in i.sectionHeaderHeight = v }
			case .sectionIndexBackgroundColor(let x): return x.apply(instance, storage) { i, s, v in i.sectionIndexBackgroundColor = v }
			case .sectionIndexColor(let x): return x.apply(instance, storage) { i, s, v in i.sectionIndexColor = v }
			case .sectionIndexMinimumDisplayRowCount(let x): return x.apply(instance, storage) { i, s, v in i.sectionIndexMinimumDisplayRowCount = v }
			case .sectionIndexTrackingBackgroundColor(let x): return x.apply(instance, storage) { i, s, v in i.sectionIndexTrackingBackgroundColor = v }
			case .selectRow(let x): return x.apply(instance, storage) { i, s, v in i.selectRow(at: v.value?.indexPath, animated: v.isAnimated, scrollPosition: v.value?.position ?? .none) }
			case .separatorColor(let x): return x.apply(instance, storage) { i, s, v in i.separatorColor = v }
			case .separatorEffect(let x): return x.apply(instance, storage) { i, s, v in i.separatorEffect = v }
			case .separatorInset(let x): return x.apply(instance, storage) { i, s, v in i.separatorInset = v }
			case .separatorStyle(let x): return x.apply(instance, storage) { i, s, v in i.separatorStyle = v }
			case .tableFooterView(let x): return x.apply(instance, storage) { i, s, v	in i.tableFooterView = v?.uiView }
			case .tableHeaderView(let x): return x.apply(instance, storage) { i, s, v in i.tableHeaderView = v?.uiView }
			case .selectionDidChange(let x):
				return Signal.notifications(name: NSNotification.Name.UITableViewSelectionDidChange, object: instance).map { n -> ([TableRow<RowData>])? in
					if let tableView = n.object as? UITableView, let selection = tableView.indexPathsForSelectedRows {
						if let rows = (tableView.delegate as? Storage)?.sections.rows {
							return selection.map { TableRow<RowData>(indexPath: $0, data: rows.at($0.section)?.rows.at($0.row)) }
						} else {
							return selection.map { TableRow<RowData>(indexPath: $0, data: nil) }
						}
					} else {
						return nil
					}
				}.cancellableBind(to: x)
			case .sectionIndexTitles(let x):
				return x.apply(instance, storage) { i, s, v in
					s.indexTitles = v
					i.reloadSectionIndexTitles()
				}
			case .tableData(let x):
				return x.apply(instance, storage) { i, s, v in
					s.applyTableRowMutation(v, to: i)
				}
			case .cellConstructor(let x):
				storage.cellConstructor = x
				return nil
			case .dataMissingCell(let x):
				storage.dataMissingCell = x
				return nil
			case .userDidScrollToRow: return nil
			case .accessoryButtonTapped: return nil
			case .canEditRow: return nil
			case .canFocusRow: return nil
			case .canMoveRow: return nil
			case .canPerformAction: return nil
			case .didDeselectRow: return nil
			case .didEndDisplayingFooter: return nil
			case .didEndDisplayingHeader: return nil
			case .didEndDisplayingRow: return nil
			case .didEndEditingRow: return nil
			case .didHightlightRow: return nil
			case .didSelectRow: return nil
			case .commit: return nil
			case .didUnhighlightRow: return nil
			case .didUpdateFocus: return nil
			case .editActionsForRow: return nil
			case .editingStyleForRow: return nil
			case .estimatedHeightForFooter: return nil
			case .estimatedHeightForHeader: return nil
			case .estimatedHeightForRow: return nil
			case .footerHeight: return nil
			case .footerView: return nil
			case .headerHeight: return nil
			case .headerView: return nil
			case .heightForRow: return nil
			case .indentationLevelForRow: return nil
			case .indexPathForPreferredFocusedView: return nil
			case .moveRow: return nil
			case .shouldHighlightRow: return nil
			case .shouldIndentWhileEditingRow: return nil
			case .shouldShowMenuForRow: return nil
			case .shouldUpdateFocus: return nil
			case .targetIndexPathForMoveFromRow: return nil
			case .titleForDeleteConfirmationButtonForRow: return nil
			case .visibleRowsChanged: return nil
			case .willBeginEditingRow: return nil
			case .willDeselectRow: return nil
			case .willDisplayFooter: return nil
			case .willDisplayHeader: return nil
			case .willDisplayRow: return nil
			case .willSelectRow: return nil
			case .inheritedBinding(let s): return linkedPreparer.applyBinding(s, instance: instance, storage: storage)
			}
		}

		mutating func prepareInstance(_ instance: Instance, storage: Storage) {
			storage.rowsChangedInput = rowsChangedInput

			linkedPreparer.prepareInstance(instance, storage: storage)
			instance.dataSource = storage
		}
	}

	class Storage: ScrollView.Storage, UITableViewDelegate, UITableViewDataSource {
		override var inUse: Bool { return true }
		var sections = TableRowState<TableSectionState<RowData>>()
		var indexTitles: [String]? = nil
		var scrollJunction: (SignalCapture<SetOrAnimate<(IndexPath, UITableViewScrollPosition)>>, SignalInput<SetOrAnimate<(IndexPath, UITableViewScrollPosition)>>)? = nil
		var cellIdentifier: (TableRow<RowData>) -> String?
		var cellConstructor: ((_ identifier: String?, _ rowSignal: SignalMulti<RowData>) -> TableViewCellConvertible)?
		var dataMissingCell: (IndexPath) -> TableViewCellConvertible = { _ in return TableViewCell() }
		
		init(cellIdentifier: @escaping (TableRow<RowData>) -> String?) {
			self.cellIdentifier = cellIdentifier
			super.init()
		}
		
		func numberOfSections(in tableView: UITableView) -> Int {
			return sections.globalCount
		}
		
		func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
			return sections.rows.at(section)?.globalCount ?? 0
		}
		
		func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
			let data = sections.rows.at(indexPath.section).flatMap { s in s.rows.at(indexPath.row - s.localOffset) }
			let identifier = cellIdentifier(TableRow(indexPath: indexPath, data: data))
			
			let cellView: UITableViewCell
			let cellInput: SignalInput<RowData>?
			if let i = identifier, let reusedView = tableView.dequeueReusableCell(withIdentifier: i) {
				cellView = reusedView
				cellInput = getSignalInput(for: reusedView, valueType: RowData.self)
			} else if let cc = cellConstructor {
				let dataTuple = Signal<RowData>.channel().multicast()
				let constructed = cc(identifier, dataTuple.signal).uiTableViewCell(reuseIdentifier: identifier)
				cellView = constructed
				cellInput = dataTuple.input
				setSignalInput(for: constructed, to: dataTuple.input)
			} else {
				return dataMissingCell(indexPath).uiTableViewCell(reuseIdentifier: nil)
			}
			
			if let d = data {
				_ = cellInput?.send(value: d)
			}
			
			return cellView
		}
		
		func tableView(_ tableView: UITableView, titleForHeaderInSection: Int) -> String? {
			return sections.rows.at(titleForHeaderInSection)?.metadata.header
		}
		
		func tableView(_ tableView: UITableView, titleForFooterInSection: Int) -> String? {
			return sections.rows.at(titleForFooterInSection)?.metadata.footer
		}
		
		func sectionIndexTitles(for tableView: UITableView) -> [String]? {
			return indexTitles
		}
		
		var rowsChangedInput: SignalInput<[TableRow<RowData>]>?
		func notifyVisibleRowsChanged(in tableView: UITableView) {
			Exec.mainAsync.invoke {
				if let input = self.rowsChangedInput {
					let indexPaths = tableView.indexPathsForVisibleRows
					if let ip = indexPaths, ip.count > 0 {
						input.send(value: ip.map { TableRow<RowData>(indexPath: $0, data: self.sections.rows.at($0.section)?.rows.at($0.row)) })
					} else {
						input.send(value: [])
					}
				}
			}
		}
		
		func applyTableRowMutation(_ v: TableRowMutation<TableSectionMutation<RowData>>, to i: UITableView) {
			v.apply(to: &sections)
			
			switch v.arrayMutation.kind {
			case .delete:
				i.deleteSections(v.arrayMutation.indexSet.offset(by: sections.localOffset), with: v.animation)
			case .move(let destination):
				i.beginUpdates()
				for (count, index) in v.arrayMutation.indexSet.offset(by: sections.localOffset).enumerated() {
					i.moveSection(index, toSection: destination + count)
				}
				i.endUpdates()
			case .insert:
				i.insertSections(v.arrayMutation.indexSet.offset(by: sections.localOffset), with: v.animation)
			case .scroll:
				i.reloadSections(v.arrayMutation.indexSet.offset(by: sections.localOffset), with: v.animation)
			case .update:
				for (sectionIndex, change) in zip(v.arrayMutation.indexSet.offset(by: sections.localOffset), v.arrayMutation.values) {
					if change.metadata != nil {
						i.reloadSections([sectionIndex], with: v.animation)
					} else {
						let mappedIndices = change.rowMutation.arrayMutation.indexSet.map { IndexPath(row: $0, section: sectionIndex) }
						switch change.rowMutation.arrayMutation.kind {
						case .delete: i.deleteRows(at: mappedIndices, with: change.rowMutation.animation)
						case .move(let destination):
							for (count, index) in mappedIndices.enumerated() {
								i.moveRow(at: index, to: IndexPath(row: destination + count, section: sectionIndex))
							}
						case .insert: i.insertRows(at: mappedIndices, with: change.rowMutation.animation)
						case .scroll:
							i.reloadRows(at: mappedIndices, with: change.rowMutation.animation)
						case .update:
							guard let section = sections.rows.at(sectionIndex - sections.localOffset) else { continue }
							for indexPath in mappedIndices {
								guard let cell = i.cellForRow(at: indexPath), let value = section.rows.at(indexPath.row - section.rowState.localOffset) else { continue }
								getSignalInput(for: cell, valueType: RowData.self)?.send(value: value)
							}
							notifyVisibleRowsChanged(in: i)
						case .reload:
							i.reloadSections([sectionIndex], with: change.rowMutation.animation)
						}
					}
				}
			case .reload:
				i.reloadData()
			}
		}
	}

	class Delegate: ScrollView.Delegate, UITableViewDataSource, UITableViewDelegate {
		required init() {
			super.init()
		}
		
		var userDidScrollToRow: SignalInput<TableRow<RowData>>?

		override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
			super.scrollViewDidEndDragging(scrollView, willDecelerate: decelerate)
			if !decelerate, let tableView = scrollView as? UITableView, let topVisibleRow = tableView.indexPathsForVisibleRows?.last {
				userDidScrollToRow?.send(value: tableRowData(at: topVisibleRow, in: tableView))
			}
		}
		
		override func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
			super.scrollViewDidScrollToTop(scrollView)
			if let tableView = scrollView as? UITableView, let topVisibleRow = tableView.indexPathsForVisibleRows?.last {
				userDidScrollToRow?.send(value: tableRowData(at: topVisibleRow, in: tableView))
			}
		}
		
		override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
			super.scrollViewDidEndDecelerating(scrollView)
			if let tableView = scrollView as? UITableView, let topVisibleRow = tableView.indexPathsForVisibleRows?.last {
				userDidScrollToRow?.send(value: tableRowData(at: topVisibleRow, in: tableView))
			}
		}

		private func tableRowData(at indexPath: IndexPath, in tableView: UITableView) -> TableRow<RowData> {
			return TableRow<RowData>(indexPath: indexPath, data: (tableView.delegate as? Storage)?.sections.rows.at(indexPath.section)?.rows.at(indexPath.row))
		}
		
		func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
			return 0
		}
		func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
			return UITableViewCell()
		}
		
		var accessoryButtonTapped: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
			accessoryButtonTapped?.send(value: tableRowData(at: indexPath, in: tableView))
		}
		
		var canEditRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
			return canEditRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var canFocusRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool {
			return canFocusRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var canMoveRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
			return canMoveRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var canPerformAction: ((_ action: Selector, _ tableRowData: TableRow<RowData>, _ sender: Any?) -> Bool)?
		func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
			return canPerformAction!(action, tableRowData(at: indexPath, in: tableView), sender)
		}
		
		var didDeselectRow: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
			didDeselectRow?.send(value: tableRowData(at: indexPath, in: tableView))
		}
		
		var didEndDisplayingHeader: SignalInput<Int>?
		func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int) {
			didEndDisplayingHeader?.send(value: section)
		}
		
		var didEndDisplayingFooter: SignalInput<Int>?
		func tableView(_ tableView: UITableView, didEndDisplayingFooterView view: UIView, forSection section: Int) {
			didEndDisplayingFooter?.send(value: section)
		}
		
		var didEndDisplayingRow: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
			didEndDisplayingRow?.send(value: tableRowData(at: indexPath, in: tableView))
			
			(tableView.delegate as? Storage)?.notifyVisibleRowsChanged(in: tableView)
		}
		
		var didEndEditingRow: SignalInput<TableRow<RowData>?>?
		func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
			didEndEditingRow?.send(value: indexPath.map { tableRowData(at: $0, in: tableView) })
		}
		
		var didHightlightRow: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
			didHightlightRow?.send(value: tableRowData(at: indexPath, in: tableView))
		}
		
		var didSelectRow: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
			didSelectRow?.send(value: tableRowData(at: indexPath, in: tableView))
		}
		
		var didUnhighlightRow: SignalInput<TableRow<RowData>>?
		func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) {
			didUnhighlightRow?.send(value: tableRowData(at: indexPath, in: tableView))
		}
		
		var didUpdateFocus: ((UITableView, UITableViewFocusUpdateContext, UIFocusAnimationCoordinator) -> Void)?
		func tableView(_ tableView: UITableView, didUpdateFocusIn context: UITableViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
			return didUpdateFocus!(tableView, context, coordinator)
		}
		
		var editActionsForRow: ((_ tableRowData: TableRow<RowData>) -> [UITableViewRowAction]?)?
		func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
			return editActionsForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var editingStyleForRow: ((_ tableRowData: TableRow<RowData>) -> UITableViewCellEditingStyle)?
		func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
			return editingStyleForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var estimatedHeightForFooter: ((_ section: Int) -> CGFloat)?
		func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
			return estimatedHeightForFooter!(section)
		}
		
		var estimatedHeightForHeader: ((_ section: Int) -> CGFloat)?
		func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
			return estimatedHeightForHeader!(section)
		}
		
		var estimatedHeightForRow: ((_ tableRowData: TableRow<RowData>) -> CGFloat)?
		func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
			return estimatedHeightForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var footerHeight: ((_ section: Int) -> CGFloat)?
		func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
			return footerHeight!(section)
		}
		
		var footerView: ((_ section: Int, _ title: String?) -> ViewConvertible?)?
		func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
			return footerView!(section, tableView.dataSource?.tableView?(tableView, titleForFooterInSection: section))?.uiView
		}
		
		var headerHeight: ((_ section: Int) -> CGFloat)?
		func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
			return headerHeight!(section)
		}
		
		var headerView: ((_ section: Int, _ title: String?) -> ViewConvertible?)?
		func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
			return headerView!(section, tableView.dataSource?.tableView?(tableView, titleForHeaderInSection: section))?.uiView
		}
		
		var heightForRow: ((_ tableRowData: TableRow<RowData>) -> CGFloat)?
		func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
			return heightForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var indentationLevelForRow: ((_ tableRowData: TableRow<RowData>) -> Int)?
		func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int {
			return indentationLevelForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var indexPathForPreferred: ((UITableView) -> IndexPath)?
		func indexPathForPreferredFocusedView(in tableView: UITableView) -> IndexPath? {
			return indexPathForPreferred!(tableView)
		}
		
		var moveRow: SignalInput<(from: TableRow<RowData>, to: IndexPath)>?
		func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
			moveRow!.send(value: (from: tableRowData(at: sourceIndexPath, in: tableView), to: destinationIndexPath))
		}
		
		var shouldHighlightRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
			return shouldHighlightRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var shouldIndentWhileEditingRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
			return shouldIndentWhileEditingRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var shouldShowMenuForRow: ((_ tableRowData: TableRow<RowData>) -> Bool)?
		func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
			return shouldShowMenuForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var shouldUpdateFocus: ((UITableView, UITableViewFocusUpdateContext) -> Bool)?
		func tableView(_ tableView: UITableView, shouldUpdateFocusIn context: UITableViewFocusUpdateContext) -> Bool {
			return shouldUpdateFocus!(tableView, context)
		}
		
		var targetIndexPathForMoveFromRow: ((_ tableView: UITableView, _ sourceIndexPath: IndexPath, _ proposedIndexPath: IndexPath) -> IndexPath)?
		func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
			return targetIndexPathForMoveFromRow!(tableView, sourceIndexPath, proposedDestinationIndexPath)
		}
		
		var titleForDeleteConfirmationButtonForRow: ((_ tableRowData: TableRow<RowData>) -> String?)?
		func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
			return titleForDeleteConfirmationButtonForRow!(tableRowData(at: indexPath, in: tableView))
		}
		
		var willBeginEditingRow: ((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> Void)?
		func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
			willBeginEditingRow!(tableView, tableRowData(at: indexPath, in: tableView))
		}
		
		var willDeselectRow: ((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> IndexPath?)?
		func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
			return willDeselectRow!(tableView, tableRowData(at: indexPath, in: tableView))
		}
		
		var willDisplayFooter: ((_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void)?
		func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
			willDisplayFooter!(tableView, section, view)
		}
		
		var willDisplayHeader: ((_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void)?
		func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
			willDisplayHeader!(tableView, section, view)
		}
		
		var willDisplayRow: ((_ tableView: UITableView, _ indexPath: IndexPath, _ cell: UITableViewCell) -> Void)?
		func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
			willDisplayRow?(tableView, indexPath, cell)
			(tableView.delegate as? Storage)?.notifyVisibleRowsChanged(in: tableView)
		}
		
		var willSelectRow: ((_ tableView: UITableView, _ tableRowData: TableRow<RowData>) -> IndexPath?)?
		func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
			return willSelectRow!(tableView, tableRowData(at: indexPath, in: tableView))
		}
		
		var commit: SignalInput<(editingStyle: UITableViewCellEditingStyle, row: TableRow<RowData>)>?
		func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
			commit?.send(value: (editingStyle, tableRowData(at: indexPath, in: tableView)))
		}
	}
}

extension BindingName where Binding: TableViewBinding {
	// You can easily convert the `Binding` cases to `BindingName` using the following Xcode-style regex:
	// Replace: case ([^\(]+)\((.+)\)$
	// With:    static var $1: BindingName<$2, Binding> { return BindingName<$2, Binding>({ v in .tableViewBinding(TableView.Binding.$1(v)) }) }
	static var cellIdentifier: BindingName<(TableRow<Binding.RowDataType>) -> String?, Binding> { return BindingName<(TableRow<Binding.RowDataType>) -> String?, Binding>({ v in .tableViewBinding(TableView.Binding.cellIdentifier(v)) }) }
	static var tableViewStyle: BindingName<StaticValue<UITableViewStyle>, Binding> { return BindingName<StaticValue<UITableViewStyle>, Binding>({ v in .tableViewBinding(TableView.Binding.tableViewStyle(v)) }) }
	static var allowsMultipleSelection: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.allowsMultipleSelection(v)) }) }
	static var allowsMultipleSelectionDuringEditing: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.allowsMultipleSelectionDuringEditing(v)) }) }
	static var allowsSelection: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.allowsSelection(v)) }) }
	static var allowsSelectionDuringEditing: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.allowsSelectionDuringEditing(v)) }) }
	static var backgroundView: BindingName<DynamicValue<ViewConvertible?>, Binding> { return BindingName<DynamicValue<ViewConvertible?>, Binding>({ v in .tableViewBinding(TableView.Binding.backgroundView(v)) }) }
	static var cellLayoutMarginsFollowReadableWidth: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.cellLayoutMarginsFollowReadableWidth(v)) }) }
	static var isEditing: BindingName<Signal<SetOrAnimate<Bool>>, Binding> { return BindingName<Signal<SetOrAnimate<Bool>>, Binding>({ v in .tableViewBinding(TableView.Binding.isEditing(v)) }) }
	static var estimatedRowHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedRowHeight(v)) }) }
	static var estimatedSectionFooterHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedSectionFooterHeight(v)) }) }
	static var estimatedSectionHeaderHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedSectionHeaderHeight(v)) }) }
	static var remembersLastFocusedIndexPath: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .tableViewBinding(TableView.Binding.remembersLastFocusedIndexPath(v)) }) }
	static var rowHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.rowHeight(v)) }) }
	static var sectionFooterHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionFooterHeight(v)) }) }
	static var sectionHeaderHeight: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionHeaderHeight(v)) }) }
	static var sectionIndexBackgroundColor: BindingName<DynamicValue<UIColor?>, Binding> { return BindingName<DynamicValue<UIColor?>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionIndexBackgroundColor(v)) }) }
	static var sectionIndexColor: BindingName<DynamicValue<UIColor?>, Binding> { return BindingName<DynamicValue<UIColor?>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionIndexColor(v)) }) }
	static var sectionIndexMinimumDisplayRowCount: BindingName<DynamicValue<Int>, Binding> { return BindingName<DynamicValue<Int>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionIndexMinimumDisplayRowCount(v)) }) }
	static var sectionIndexTrackingBackgroundColor: BindingName<DynamicValue<UIColor?>, Binding> { return BindingName<DynamicValue<UIColor?>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionIndexTrackingBackgroundColor(v)) }) }
	static var sectionIndexTitles: BindingName<DynamicValue<[String]?>, Binding> { return BindingName<DynamicValue<[String]?>, Binding>({ v in .tableViewBinding(TableView.Binding.sectionIndexTitles(v)) }) }
	static var separatorColor: BindingName<DynamicValue<UIColor?>, Binding> { return BindingName<DynamicValue<UIColor?>, Binding>({ v in .tableViewBinding(TableView.Binding.separatorColor(v)) }) }
	static var separatorEffect: BindingName<DynamicValue<UIVisualEffect?>, Binding> { return BindingName<DynamicValue<UIVisualEffect?>, Binding>({ v in .tableViewBinding(TableView.Binding.separatorEffect(v)) }) }
	static var separatorInset: BindingName<DynamicValue<UIEdgeInsets>, Binding> { return BindingName<DynamicValue<UIEdgeInsets>, Binding>({ v in .tableViewBinding(TableView.Binding.separatorInset(v)) }) }
	static var separatorStyle: BindingName<DynamicValue<UITableViewCellSeparatorStyle>, Binding> { return BindingName<DynamicValue<UITableViewCellSeparatorStyle>, Binding>({ v in .tableViewBinding(TableView.Binding.separatorStyle(v)) }) }
	static var tableFooterView: BindingName<DynamicValue<ViewConvertible?>, Binding> { return BindingName<DynamicValue<ViewConvertible?>, Binding>({ v in .tableViewBinding(TableView.Binding.tableFooterView(v)) }) }
	static var tableHeaderView: BindingName<DynamicValue<ViewConvertible?>, Binding> { return BindingName<DynamicValue<ViewConvertible?>, Binding>({ v in .tableViewBinding(TableView.Binding.tableHeaderView(v)) }) }
	static var tableData: BindingName<DynamicValue<TableData<Binding.RowDataType>>, Binding> { return BindingName<DynamicValue<TableData<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.tableData(v)) }) }
	static var deselectRow: BindingName<Signal<SetOrAnimate<IndexPath>>, Binding> { return BindingName<Signal<SetOrAnimate<IndexPath>>, Binding>({ v in .tableViewBinding(TableView.Binding.deselectRow(v)) }) }
	static var scrollToNearestSelectedRow: BindingName<Signal<SetOrAnimate<UITableViewScrollPosition>>, Binding> { return BindingName<Signal<SetOrAnimate<UITableViewScrollPosition>>, Binding>({ v in .tableViewBinding(TableView.Binding.scrollToNearestSelectedRow(v)) }) }
	static var scrollToRow: BindingName<Signal<SetOrAnimate<TableScrollPosition>>, Binding> { return BindingName<Signal<SetOrAnimate<TableScrollPosition>>, Binding>({ v in .tableViewBinding(TableView.Binding.scrollToRow(v)) }) }
	static var selectRow: BindingName<Signal<SetOrAnimate<TableScrollPosition?>>, Binding> { return BindingName<Signal<SetOrAnimate<TableScrollPosition?>>, Binding>({ v in .tableViewBinding(TableView.Binding.selectRow(v)) }) }
	static var userDidScrollToRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.userDidScrollToRow(v)) }) }
	static var accessoryButtonTapped: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.accessoryButtonTapped(v)) }) }
	static var didDeselectRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.didDeselectRow(v)) }) }
	static var didEndDisplayingFooter: BindingName<SignalInput<Int>, Binding> { return BindingName<SignalInput<Int>, Binding>({ v in .tableViewBinding(TableView.Binding.didEndDisplayingFooter(v)) }) }
	static var didEndDisplayingHeader: BindingName<SignalInput<Int>, Binding> { return BindingName<SignalInput<Int>, Binding>({ v in .tableViewBinding(TableView.Binding.didEndDisplayingHeader(v)) }) }
	static var didEndDisplayingRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.didEndDisplayingRow(v)) }) }
	static var didEndEditingRow: BindingName<SignalInput<TableRow<Binding.RowDataType>?>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>?>, Binding>({ v in .tableViewBinding(TableView.Binding.didEndEditingRow(v)) }) }
	static var didHightlightRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.didHightlightRow(v)) }) }
	static var didSelectRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.didSelectRow(v)) }) }
	static var didUnhighlightRow: BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding> { return BindingName<SignalInput<TableRow<Binding.RowDataType>>, Binding>({ v in .tableViewBinding(TableView.Binding.didUnhighlightRow(v)) }) }
	static var moveRow: BindingName<SignalInput<(from: TableRow<Binding.RowDataType>, to: IndexPath)>, Binding> { return BindingName<SignalInput<(from: TableRow<Binding.RowDataType>, to: IndexPath)>, Binding>({ v in .tableViewBinding(TableView.Binding.moveRow(v)) }) }
	static var selectionDidChange: BindingName<SignalInput<[TableRow<Binding.RowDataType>]?>, Binding> { return BindingName<SignalInput<[TableRow<Binding.RowDataType>]?>, Binding>({ v in .tableViewBinding(TableView.Binding.selectionDidChange(v)) }) }
	static var visibleRowsChanged: BindingName<SignalInput<[TableRow<Binding.RowDataType>]>, Binding> { return BindingName<SignalInput<[TableRow<Binding.RowDataType>]>, Binding>({ v in .tableViewBinding(TableView.Binding.visibleRowsChanged(v)) }) }
	static var commit: BindingName<SignalInput<(editingStyle: UITableViewCellEditingStyle, row: TableRow<Binding.RowDataType>)>, Binding> { return BindingName<SignalInput<(editingStyle: UITableViewCellEditingStyle, row: TableRow<Binding.RowDataType>)>, Binding>({ v in .tableViewBinding(TableView.Binding.commit(v)) }) }
	static var canEditRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.canEditRow(v)) }) }
	static var canFocusRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.canFocusRow(v)) }) }
	static var canMoveRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.canMoveRow(v)) }) }
	static var canPerformAction: BindingName<(_ action: Selector, _ tableRowData: TableRow<Binding.RowDataType>, _ sender: Any?) -> Bool, Binding> { return BindingName<(_ action: Selector, _ tableRowData: TableRow<Binding.RowDataType>, _ sender: Any?) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.canPerformAction(v)) }) }
	static var cellConstructor: BindingName<(_ identifier: String?, _ rowSignal: Signal<Binding.RowDataType>) -> TableViewCellConvertible, Binding> { return BindingName<(_ identifier: String?, _ rowSignal: Signal<Binding.RowDataType>) -> TableViewCellConvertible, Binding>({ v in .tableViewBinding(TableView.Binding.cellConstructor(v)) }) }
	static var dataMissingCell: BindingName<(IndexPath) -> TableViewCellConvertible, Binding> { return BindingName<(IndexPath) -> TableViewCellConvertible, Binding>({ v in .tableViewBinding(TableView.Binding.dataMissingCell(v)) }) }
	static var didUpdateFocus: BindingName<(UITableView, UITableViewFocusUpdateContext, UIFocusAnimationCoordinator) -> Void, Binding> { return BindingName<(UITableView, UITableViewFocusUpdateContext, UIFocusAnimationCoordinator) -> Void, Binding>({ v in .tableViewBinding(TableView.Binding.didUpdateFocus(v)) }) }
	static var editActionsForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> [UITableViewRowAction]?, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> [UITableViewRowAction]?, Binding>({ v in .tableViewBinding(TableView.Binding.editActionsForRow(v)) }) }
	static var editingStyleForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> UITableViewCellEditingStyle, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> UITableViewCellEditingStyle, Binding>({ v in .tableViewBinding(TableView.Binding.editingStyleForRow(v)) }) }
	static var estimatedHeightForFooter: BindingName<(_ section: Int) -> CGFloat, Binding> { return BindingName<(_ section: Int) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedHeightForFooter(v)) }) }
	static var estimatedHeightForHeader: BindingName<(_ section: Int) -> CGFloat, Binding> { return BindingName<(_ section: Int) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedHeightForHeader(v)) }) }
	static var estimatedHeightForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> CGFloat, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.estimatedHeightForRow(v)) }) }
	static var footerHeight: BindingName<(_ section: Int) -> CGFloat, Binding> { return BindingName<(_ section: Int) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.footerHeight(v)) }) }
	static var footerView: BindingName<(_ section: Int, _ title: String?) -> ViewConvertible?, Binding> { return BindingName<(_ section: Int, _ title: String?) -> ViewConvertible?, Binding>({ v in .tableViewBinding(TableView.Binding.footerView(v)) }) }
	static var headerHeight: BindingName<(_ section: Int) -> CGFloat, Binding> { return BindingName<(_ section: Int) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.headerHeight(v)) }) }
	static var headerView: BindingName<(_ section: Int, _ title: String?) -> ViewConvertible?, Binding> { return BindingName<(_ section: Int, _ title: String?) -> ViewConvertible?, Binding>({ v in .tableViewBinding(TableView.Binding.headerView(v)) }) }
	static var heightForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> CGFloat, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> CGFloat, Binding>({ v in .tableViewBinding(TableView.Binding.heightForRow(v)) }) }
	static var indentationLevelForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Int, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Int, Binding>({ v in .tableViewBinding(TableView.Binding.indentationLevelForRow(v)) }) }
	static var indexPathForPreferredFocusedView: BindingName<(UITableView) -> IndexPath, Binding> { return BindingName<(UITableView) -> IndexPath, Binding>({ v in .tableViewBinding(TableView.Binding.indexPathForPreferredFocusedView(v)) }) }
	static var shouldHighlightRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.shouldHighlightRow(v)) }) }
	static var shouldIndentWhileEditingRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.shouldIndentWhileEditingRow(v)) }) }
	static var shouldShowMenuForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.shouldShowMenuForRow(v)) }) }
	static var shouldUpdateFocus: BindingName<(UITableView, UITableViewFocusUpdateContext) -> Bool, Binding> { return BindingName<(UITableView, UITableViewFocusUpdateContext) -> Bool, Binding>({ v in .tableViewBinding(TableView.Binding.shouldUpdateFocus(v)) }) }
	static var targetIndexPathForMoveFromRow: BindingName<(_ tableView: UITableView, _ sourceIndexPath: IndexPath, _ proposedIndexPath: IndexPath) -> IndexPath, Binding> { return BindingName<(_ tableView: UITableView, _ sourceIndexPath: IndexPath, _ proposedIndexPath: IndexPath) -> IndexPath, Binding>({ v in .tableViewBinding(TableView.Binding.targetIndexPathForMoveFromRow(v)) }) }
	static var titleForDeleteConfirmationButtonForRow: BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> String?, Binding> { return BindingName<(_ tableRowData: TableRow<Binding.RowDataType>) -> String?, Binding>({ v in .tableViewBinding(TableView.Binding.titleForDeleteConfirmationButtonForRow(v)) }) }
	static var willBeginEditingRow: BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> Void, Binding> { return BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> Void, Binding>({ v in .tableViewBinding(TableView.Binding.willBeginEditingRow(v)) }) }
	static var willDeselectRow: BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> IndexPath?, Binding> { return BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> IndexPath?, Binding>({ v in .tableViewBinding(TableView.Binding.willDeselectRow(v)) }) }
	static var willDisplayFooter: BindingName<(_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void, Binding> { return BindingName<(_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void, Binding>({ v in .tableViewBinding(TableView.Binding.willDisplayFooter(v)) }) }
	static var willDisplayHeader: BindingName<(_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void, Binding> { return BindingName<(_ tableView: UITableView, _ section: Int, _ view: UIView) -> Void, Binding>({ v in .tableViewBinding(TableView.Binding.willDisplayHeader(v)) }) }
	static var willDisplayRow: BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>, _ cell: UITableViewCell) -> Void, Binding> { return BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>, _ cell: UITableViewCell) -> Void, Binding>({ v in .tableViewBinding(TableView.Binding.willDisplayRow(v)) }) }
	static var willSelectRow: BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> IndexPath?, Binding> { return BindingName<(_ tableView: UITableView, _ tableRowData: TableRow<Binding.RowDataType>) -> IndexPath?, Binding>({ v in .tableViewBinding(TableView.Binding.willSelectRow(v)) }) }
}

protocol TableViewConvertible: ScrollViewConvertible {
	var uiTableView: UITableView { get }
}
extension TableViewConvertible {
	var uiScrollView: ScrollView.Instance { return uiTableView }
}
extension TableView.Instance: TableViewConvertible {
	var uiTableView: UITableView { return self }
}

protocol TableViewBinding: ScrollViewBinding {
	associatedtype RowDataType
	static func tableViewBinding(_ binding: TableView<RowDataType>.Binding) -> Self
}
extension TableViewBinding {
	static func scrollViewBinding(_ binding: ScrollView.Binding) -> Self {
		return tableViewBinding(.inheritedBinding(binding))
	}
}

typealias TableData<RowData> = TableRowMutation<TableSectionMutation<RowData>>

struct TableScrollPosition {
	let indexPath: IndexPath
	let position: UITableViewScrollPosition
	init(indexPath: IndexPath, position: UITableViewScrollPosition = .none) {
		self.indexPath = indexPath
		self.position = position
	}
	
	static func none(_ indexPath: IndexPath) -> TableScrollPosition {
		return TableScrollPosition(indexPath: indexPath, position: .none)
	}
	
	static func top(_ indexPath: IndexPath) -> TableScrollPosition {
		return TableScrollPosition(indexPath: indexPath, position: .top)
	}
	
	static func middle(_ indexPath: IndexPath) -> TableScrollPosition {
		return TableScrollPosition(indexPath: indexPath, position: .middle)
	}
	
	static func bottom(_ indexPath: IndexPath) -> TableScrollPosition {
		return TableScrollPosition(indexPath: indexPath, position: .bottom)
	}
}

func updateFirstRow<RowData>(_ storage: Var<IndexPath?>) -> SignalInput<[TableRow<RowData>]> {
	return Input().map { $0.first?.indexPath }.bind(to: storage.updatingInput)
}

extension SignalInterface where OutputValue == IndexPath? {
	func restoreFirstRow() -> Signal<SetOrAnimate<TableScrollPosition>> {
		return compactMap { $0.map { .top($0) } }.animate(.none)
	}
}

struct TableRow<RowData> {
	let indexPath: IndexPath
	let data: RowData?
	
	init(indexPath: IndexPath, data: RowData?) {
		self.indexPath = indexPath
		self.data = data
	}
}

// MARK: ### CwlApplication.swift ###

func applicationMain(subclass: UIApplication.Type = UIApplication.self, application: @escaping () -> Application) -> Never {
	Application.Storage.finish = { () -> Void in
		application().applyBindings(to: UIApplication.shared)
	}
	
	return CommandLine.unsafeArgv.withMemoryRebound(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc)) { argv -> Never in
		_ = UIApplicationMain(CommandLine.argc, argv, NSStringFromClass(subclass), NSStringFromClass(Application.Storage.self))
		fatalError("UIApplicationMain completed unexpectedly")
	}
}

class Application: Binder {
	typealias Inherited = BaseBinder
	typealias Instance = UIApplication
	
	var state: BinderState<Instance, BindingsOnlyParameters<Binding>>
	required init(state: BinderState<Instance, BindingsOnlyParameters<Binding>>) {
		self.state = state
	}
	static func bindingToInherited(_ binding: Binding) -> Inherited.Binding? {
		if case .inheritedBinding(let s) = binding { return s } else { return nil }
	}

	enum Binding: ApplicationBinding {
		typealias EnclosingBinder = Application
		static func applicationBinding(_ binding: Application.Binding) -> Application.Binding { return binding }
		case inheritedBinding(Inherited.Binding)
		
		//	1. Value bindings may be applied at construction and may subsequently change.
		case ignoreInteractionEvents(DynamicValue<Bool>)
		case supportShakeToEdit(DynamicValue<Bool>)
		case isIdleTimerDisabled(DynamicValue<Bool>)
		case shortcutItems(DynamicValue<[UIApplicationShortcutItem]?>)
		case isNetworkActivityIndicatorVisible(DynamicValue<Bool>)
		case applicationIconBadgeNumber(DynamicValue<Int>)
		case statusBarStyle(DynamicValue<UIStatusBarStyle>)
		case window(DynamicValue<WindowConvertible?>)
		case additionalWindows(DynamicValue<[WindowConvertible]>)

		//	2. Signal bindings are performed on the object after construction.

		//	3. Action bindings are triggered by the object after construction.
		case didBecomeActive(SignalInput<()>)
		case willResignActive(SignalInput<()>)
		case didEnterBackground(SignalInput<()>)
		case willEnterForeground(SignalInput<()>)
		case protectedDataWillBecomeUnavailable(SignalInput<()>)
		case protectedDataDidBecomeAvailable(SignalInput<()>)
		case didReceiveMemoryWarning(SignalInput<()>)
		case significantTimeChange(SignalInput<()>)
		case performFetch(SignalInput<SignalInput<UIBackgroundFetchResult>>)
		case handleEventsForBackgroundURLSession(SignalInput<(String, SignalInput<()>)>)
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case registerUserNotificationSettings(Signal<UIUserNotificationSettings>)
		case registerForRemoteNotifications(Signal<Bool>)
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case didRegisterUserNotifications(SignalInput<UIUserNotificationSettings>)
		case didRegisterRemoteNotifications(SignalInput<Result<Data>>)
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case didReceiveLocalNotification(SignalInput<UILocalNotification>)
		case didReceiveRemoteNotification(SignalInput<([AnyHashable: Any], SignalInput<UIBackgroundFetchResult>)>)
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case handleLocalNotificationAction(SignalInput<(String?, UILocalNotification, SignalInput<()>)>)
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case handleRemoteNotificationAction(SignalInput<(String?, [AnyHashable : Any], SignalInput<()>)>)
		@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case handleLocalNotificationResponseInfoAction(SignalInput<(String?, UILocalNotification, [AnyHashable : Any], SignalInput<()>)>)
		@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		case handleRemoteNotificationResponseInfoAction(SignalInput<(String?, [AnyHashable : Any], [AnyHashable : Any], SignalInput<()>)>)
		case didFailToContinueUserActivity(SignalInput<(String, Error)>)
		case performAction(SignalInput<(UIApplicationShortcutItem, SignalInput<Bool>)>)
		case handleWatchKitExtensionRequest(SignalInput<([AnyHashable: Any]?, SignalInput<[AnyHashable: Any]?>)>)

		//	4. Delegate bindings require synchronous evaluation within the object's context.
		case willContinueUserActivity((String) -> Bool)
		case continueUserActivity((NSUserActivity, SignalInput<[Any]?>) -> Bool)
		case didUpdate((NSUserActivity) -> Void)
		case willFinishLaunching(([UIApplicationLaunchOptionsKey: Any]?) -> Bool)
		case didFinishLaunching(([UIApplicationLaunchOptionsKey: Any]?) -> Bool)
		case willEncodeRestorableState((NSKeyedArchiver) -> Void)
		case didDecodeRestorableState((NSKeyedUnarchiver) -> Void)
		case willTerminate(() -> Void)
		case shouldSaveApplicationState((_ coder: NSCoder) -> Bool)
		case shouldRestoreApplicationState((_ coder: NSCoder) -> Bool)
		case viewControllerWithRestorationPath((_ path: [Any], _ coder: NSCoder) -> UIViewController)
		case open((_ url: URL, _ options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool)
		case shouldAllowExtensionPointIdentifier((UIApplicationExtensionPointIdentifier) -> Bool)
		case shouldRequestHealthAuthorization(() -> Void)
	}

	struct Preparer: StoragePreparer {
		typealias EnclosingBinder = Application
		var linkedPreparer = Inherited.Preparer()
		
		func constructStorage() -> EnclosingBinder.Storage {
			let storage: Storage
			if let s = Storage.underConstruction {
				storage = s
			} else {
				storage = Storage()
			}
			return storage
		}
		
		init() {
			self.init(delegateClass: Delegate.self)
		}
		init<Value>(delegateClass: Value.Type) where Value: Delegate {
			self.delegateClass = delegateClass
		}
		let delegateClass: Delegate.Type
		var possibleDelegate: Delegate? = nil
		mutating func delegate() -> Delegate {
			if let d = possibleDelegate {
				return d
			} else {
				let d = delegateClass.init()
				possibleDelegate = d
				return d
			}
		}
		
		mutating func prepareBinding(_ binding: Binding) {
			switch binding {
			case .didFinishLaunching(let x):
				let s = #selector(UIApplicationDelegate.application(_:didFinishLaunchingWithOptions:))
				delegate().addSelector(s).didFinishLaunching = x
			case .willTerminate(let x):
				let s = #selector(UIApplicationDelegate.applicationWillTerminate(_:))
				delegate().addSelector(s).willTerminate = x
			case .protectedDataWillBecomeUnavailable(let x):
				let s = #selector(UIApplicationDelegate.applicationProtectedDataWillBecomeUnavailable(_:))
				delegate().addSelector(s).protectedDataWillBecomeUnavailable = x
			case .protectedDataDidBecomeAvailable(let x):
				let s = #selector(UIApplicationDelegate.applicationProtectedDataDidBecomeAvailable(_:))
				delegate().addSelector(s).protectedDataDidBecomeAvailable = x
			case .willEncodeRestorableState(let x):
				let s = #selector(UIApplicationDelegate.application(_:willEncodeRestorableStateWith:))
				delegate().addSelector(s).willEncodeRestorableState = x
				
				// Automatically enable `shouldSaveApplicationState` if `willEncodeRestorableState` is isEnabled
				if delegate().shouldSaveApplicationState == nil {
					let shouldSave = #selector(UIApplicationDelegate.application(_:shouldSaveApplicationState:))
					delegate().addSelector(shouldSave).shouldSaveApplicationState = { _ in return true }
				}
			case .didDecodeRestorableState(let x):
				let s = #selector(UIApplicationDelegate.application(_:didDecodeRestorableStateWith:))
				delegate().addSelector(s).didDecodeRestorableState = x
				
				// Automatically enable `shouldRestoreApplicationState` if `didDecodeRestorableState` is isEnabled
				if delegate().shouldRestoreApplicationState == nil {
					let shouldRestore = #selector(UIApplicationDelegate.application(_:shouldRestoreApplicationState:))
					delegate().addSelector(shouldRestore).shouldRestoreApplicationState = { _ in return true }
				}
			case .performFetch(let x):
				let s = #selector(UIApplicationDelegate.application(_:performFetchWithCompletionHandler:))
				delegate().addSelector(s).performFetch = x
			case .handleEventsForBackgroundURLSession(let x):
				let s = #selector(UIApplicationDelegate.application(_:handleEventsForBackgroundURLSession:completionHandler:))
				delegate().addSelector(s).handleEventsForBackgroundURLSession = x
			case .didRegisterUserNotifications(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:didRegister:))
					delegate().addSelector(s).didRegisterUserNotifications = x
				}
			case .didRegisterRemoteNotifications(let x):
				let s1 = #selector(UIApplicationDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:))
				let s2 = #selector(UIApplicationDelegate.application(_:didFailToRegisterForRemoteNotificationsWithError:))
				delegate().addSelector(s1).didRegisterRemoteNotifications = x
				delegate().addSelector(s2)
			case .didReceiveLocalNotification(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:didReceive:))
					delegate().addSelector(s).didReceiveLocalNotification = x
				}
			case .didReceiveRemoteNotification(let x):
				let s = #selector(UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
				delegate().addSelector(s).didReceiveRemoteNotification = x
			case .handleLocalNotificationAction(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:handleActionWithIdentifier:for:completionHandler:))
					delegate().addSelector(s).handleLocalNotificationAction = x
				}
			case .handleRemoteNotificationAction(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:handleActionWithIdentifier:forRemoteNotification:completionHandler:))
					delegate().addSelector(s).handleRemoteNotificationAction = x
				}
			case .handleLocalNotificationResponseInfoAction(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:didReceive:))
					delegate().addSelector(s).handleLocalNotificationResponseInfoAction = x
				}
			case .handleRemoteNotificationResponseInfoAction(let x):
				if #available(iOS 10.0, *) {
					break
				} else {
					let s = #selector(UIApplicationDelegate.application(_:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:))
					delegate().addSelector(s).handleRemoteNotificationResponseInfoAction = x
				}
			case .didFailToContinueUserActivity(let x):
				let s = #selector(UIApplicationDelegate.application(_:didFailToContinueUserActivityWithType:error:))
				delegate().addSelector(s).didFailToContinueUserActivity = x
			case .performAction(let x):
				let s = #selector(UIApplicationDelegate.application(_:performActionFor:completionHandler:))
				delegate().addSelector(s).performAction = x
			case .handleWatchKitExtensionRequest(let x):
				let s = #selector(UIApplicationDelegate.application(_:handleWatchKitExtensionRequest:reply:))
				delegate().addSelector(s).handleWatchKitExtensionRequest = x
			case .shouldRequestHealthAuthorization(let x):
				let s = #selector(UIApplicationDelegate.applicationShouldRequestHealthAuthorization(_:))
				delegate().addSelector(s).shouldRequestHealthAuthorization = x
			case .willContinueUserActivity(let x):
				let s = #selector(UIApplicationDelegate.application(_:willContinueUserActivityWithType:))
				delegate().addSelector(s).willContinueUserActivity = x
			case .continueUserActivity(let x):
				let s = #selector(UIApplicationDelegate.application(_:continue:restorationHandler:))
				delegate().addSelector(s).continueUserActivity = x
			case .didUpdate(let x):
				let s = #selector(UIApplicationDelegate.application(_:didUpdate:))
				delegate().addSelector(s).didUpdate = x
			case .shouldSaveApplicationState(let x):
				let s = #selector(UIApplicationDelegate.application(_:shouldSaveApplicationState:))
				delegate().addSelector(s).shouldSaveApplicationState = x
			case .shouldRestoreApplicationState(let x):
				let s = #selector(UIApplicationDelegate.application(_:shouldRestoreApplicationState:))
				delegate().addSelector(s).shouldRestoreApplicationState = x
			case .viewControllerWithRestorationPath(let x):
				let s = #selector(UIApplicationDelegate.application(_:viewControllerWithRestorationIdentifierPath:coder:))
				delegate().addSelector(s).viewControllerWithRestorationPath = x
			case .open(let x):
				if #available(iOS 9.0, *) {
					let s = #selector(UIApplicationDelegate.application(_:open:options:))
					delegate().addSelector(s).open = x
				}
			case .shouldAllowExtensionPointIdentifier(let x):
				let s = #selector(UIApplicationDelegate.application(_:shouldAllowExtensionPointIdentifier:))
				delegate().addSelector(s).shouldAllowExtensionPointIdentifier = x
			case .inheritedBinding(let s): linkedPreparer.prepareBinding(s)
			default: break
			}
		}
		
		mutating func prepareInstance(_ instance: Instance, storage: Storage) {
			precondition(instance.delegate == nil, "Conflicting delegate applied to instance")
			storage.dynamicDelegate = possibleDelegate
			instance.delegate = storage

			linkedPreparer.prepareInstance(instance, storage: storage)
		}
		
		func applyBinding(_ binding: Binding, instance: Instance, storage: Storage) -> Cancellable? {
			switch binding {
			case .additionalWindows(let x):
				return x.apply(instance, storage) { i, s, v in
					s.additionalWindows = v.map { $0.uiWindow }
				}
			case .window(let x):
				return x.apply(instance, storage) { i, s, v in
					s.window = v?.uiWindow
				}
			case .ignoreInteractionEvents(let x):
				return x.apply(instance, storage) { i, s, v in
					switch (i.isIgnoringInteractionEvents, v) {
					case (false, true): i.beginIgnoringInteractionEvents()
					case (true, false): i.endIgnoringInteractionEvents()
					default: break
					}
				}
			case .supportShakeToEdit(let x): return x.apply(instance, storage) { i, s, v in i.applicationSupportsShakeToEdit = v }
			case .isIdleTimerDisabled(let x): return x.apply(instance, storage) { i, s, v in i.isIdleTimerDisabled = v }
			case .shortcutItems(let x): return x.apply(instance, storage) { i, s, v in i.shortcutItems = v }
			case .isNetworkActivityIndicatorVisible(let x): return x.apply(instance, storage) { i, s, v in i.isNetworkActivityIndicatorVisible = v }
			case .applicationIconBadgeNumber(let x): return x.apply(instance, storage) { i, s, v in i.applicationIconBadgeNumber = v }
			case .statusBarStyle(let x): return x.apply(instance, storage) { i, s, v in i.statusBarStyle = v }
			case .registerForRemoteNotifications(let x):
				return x.apply(instance, storage) { i, s, v in
					switch (i.isRegisteredForRemoteNotifications, v) {
					case (false, true): i.registerForRemoteNotifications()
					case (true, false): i.unregisterForRemoteNotifications()
					default: break
					}
				}
			case .registerUserNotificationSettings(let x):
				if #available(iOS 10.0, *) {
					return nil
				} else {
					return x.apply(instance, storage) { i, s, v in
						switch i.currentUserNotificationSettings {
						case .some(let a) where a != v: i.registerUserNotificationSettings(v)
						case .none: i.registerUserNotificationSettings(v)
						default: break
						}
					}
				}
			case .didBecomeActive(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationDidBecomeActive, object: instance).map { n in return () }.cancellableBind(to: x)
			case .willResignActive(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationWillResignActive, object: instance).map { n in return () }.cancellableBind(to: x)
			case .didEnterBackground(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationDidEnterBackground, object: instance).map { n in return () }.cancellableBind(to: x)
			case .willEnterForeground(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationWillEnterForeground, object: instance).map { n in return () }.cancellableBind(to: x)
			case .didReceiveMemoryWarning(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationDidReceiveMemoryWarning, object: instance).map { n in return () }.cancellableBind(to: x)
			case .significantTimeChange(let x):
				return Signal.notifications(name: NSNotification.Name.UIApplicationSignificantTimeChange, object: instance).map { n in return () }.cancellableBind(to: x)
			case .willFinishLaunching(let x):
				storage.willFinishLaunching = x
				return nil
			case .didFinishLaunching: return nil
			case .protectedDataWillBecomeUnavailable: return nil
			case .protectedDataDidBecomeAvailable: return nil
			case .performFetch: return nil
			case .handleEventsForBackgroundURLSession: return nil
			case .didRegisterUserNotifications: return nil
			case .didRegisterRemoteNotifications: return nil
			case .didReceiveLocalNotification: return nil
			case .didReceiveRemoteNotification: return nil
			case .handleLocalNotificationAction: return nil
			case .handleRemoteNotificationAction: return nil
			case .handleLocalNotificationResponseInfoAction: return nil
			case .handleRemoteNotificationResponseInfoAction: return nil
			case .didFailToContinueUserActivity: return nil
			case .performAction: return nil
			case .handleWatchKitExtensionRequest: return nil
			case .shouldRequestHealthAuthorization: return nil
				
			case .willContinueUserActivity: return nil
			case .continueUserActivity: return nil
			case .didUpdate: return nil
			case .willEncodeRestorableState: return nil
			case .didDecodeRestorableState: return nil
			case .willTerminate: return nil
			case .shouldSaveApplicationState: return nil
			case .shouldRestoreApplicationState: return nil
			case .viewControllerWithRestorationPath: return nil
			case .open: return nil
			case .shouldAllowExtensionPointIdentifier: return nil
			case .inheritedBinding(let s): return linkedPreparer.applyBinding(s, instance: instance, storage: storage)
			}
		}
	}

	class Storage: ObjectBinderStorage, UIApplicationDelegate {
		static var finish: (() -> Void)? = nil
		fileprivate static var underConstruction: Storage? = nil
		
		var window: UIWindow? = nil
		var additionalWindows: [UIWindow] = []
		
		var willFinishLaunching: (([UIApplicationLaunchOptionsKey: Any]?) -> Bool)?
		func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
			// Disconnect the delegate since we're about to change behavior
			UIApplication.shared.delegate = nil
			
			// Apply the styles to the application and delegate.
			if let finish = Storage.finish {
				Storage.underConstruction = self
				finish()
				Storage.underConstruction = nil
				Storage.finish = nil
			} else {
				preconditionFailure("Application bindings must be initialized by calling applicationMain.")
			}
			
			assert(UIApplication.shared.delegate === self, "Failed to reconnect delegate")
			
			
			// Apply the view hierarchy
			window?.makeKeyAndVisible()
			
			// Invoke any user-supplied code
			return willFinishLaunching?(launchOptions) ?? true
		}
		
		override var inUse: Bool {
			return true
		}
	}

	class Delegate: DynamicDelegate, UIApplicationDelegate {
		required override init() {
			super.init()
		}
		
		var didFinishLaunching: (([UIApplicationLaunchOptionsKey: Any]?) -> Bool)?
		func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
			return didFinishLaunching!(launchOptions)
		}
		
		var willTerminate: (() -> Void)?
		func applicationWillTerminate(_ application: UIApplication) {
			return willTerminate!()
		}
		
		var protectedDataWillBecomeUnavailable: SignalInput<()>?
		func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
			protectedDataWillBecomeUnavailable!.send(value: ())
		}
		
		var protectedDataDidBecomeAvailable: SignalInput<()>?
		func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
			protectedDataDidBecomeAvailable!.send(value: ())
		}
		
		var willEncodeRestorableState: ((NSKeyedArchiver) -> Void)?
		func application(_ application: UIApplication, willEncodeRestorableStateWith coder: NSCoder) {
			return willEncodeRestorableState!(coder as! NSKeyedArchiver)
		}
		
		var didDecodeRestorableState: ((NSKeyedUnarchiver) -> Void)?
		func application(_ application: UIApplication, didDecodeRestorableStateWith coder: NSCoder) {
			return didDecodeRestorableState!(coder as! NSKeyedUnarchiver)
		}
		
		var performFetch: SignalInput<SignalInput<UIBackgroundFetchResult>>?
		func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
			let (input, _) = Signal<UIBackgroundFetchResult>.create { s in
				s.subscribeUntilEnd { r in
					switch r {
					case .success(let bfr): completionHandler(bfr)
					case .failure: completionHandler(UIBackgroundFetchResult.failed)
					}
				}
			}
			performFetch!.send(value: input)
		}
		
		var handleEventsForBackgroundURLSession: SignalInput<(String, SignalInput<()>)>?
		func application(_ application: UIApplication, handleEventsForBackgroundURLSession session: String, completionHandler: @escaping () -> Void) {
			let (input, _) = Signal<()>.create { s in s.subscribeWhile { r in completionHandler(); return false } }
			handleEventsForBackgroundURLSession!.send(value: (session, input))
		}
		
		var didRegisterUserNotifications: Any?
		@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
			(didRegisterUserNotifications as! SignalInput<UIUserNotificationSettings>).send(value: notificationSettings)
		}
		
		var didRegisterRemoteNotifications: SignalInput<Result<Data>>?
		func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
			didRegisterRemoteNotifications!.send(value: Result.success(deviceToken))
		}
		func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
			didRegisterRemoteNotifications!.send(value: Result.failure(error))
		}
		
		var didReceiveLocalNotification: Any?
		@available(iOS, introduced: 4.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		func application(_ application: UIApplication, didReceive: UILocalNotification) {
			(didReceiveLocalNotification as! SignalInput<UILocalNotification>).send(value: didReceive)
		}
		
		var didReceiveRemoteNotification: SignalInput<([AnyHashable: Any], SignalInput<UIBackgroundFetchResult>)>?
		func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
			let (input, _) = Signal<UIBackgroundFetchResult>.create { s in
				s.subscribeUntilEnd { r in
					switch r {
					case .success(let bfr): completionHandler(bfr)
					case .failure: completionHandler(UIBackgroundFetchResult.failed)
					}
				}
			}
			didReceiveRemoteNotification!.send(value: (userInfo, input))
		}
		
		var handleLocalNotificationAction: Any?
		@available(iOS, introduced: 4.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for localNotification: UILocalNotification, completionHandler: @escaping () -> Void) {
			let (input, _) = Signal<()>.create { s in s.subscribeWhile { r in completionHandler(); return false } }
			(handleLocalNotificationAction as! SignalInput<(String?, UILocalNotification, SignalInput<()>)>).send(value: (identifier, localNotification, input))
		}
		
		var handleRemoteNotificationAction: SignalInput<(String?, [AnyHashable: Any], SignalInput<()>)>?
		func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable: Any], completionHandler: @escaping () -> Void) {
			let (input, _) = Signal<()>.create { s in s.subscribeWhile { r in completionHandler(); return false } }
			handleRemoteNotificationAction!.send(value: (identifier, userInfo, input))
		}
		
		var handleLocalNotificationResponseInfoAction: Any?
		@available(iOS, introduced: 4.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
		func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for localNotification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
			let (input, _) = Signal<()>.create { s in s.subscribeWhile { r in completionHandler(); return false } }
			(handleLocalNotificationResponseInfoAction as! SignalInput<(String?, UILocalNotification, [AnyHashable : Any], SignalInput<()>)>).send(value: (identifier, localNotification, responseInfo, input))
		}
		
		var handleRemoteNotificationResponseInfoAction: SignalInput<(String?, [AnyHashable: Any], [AnyHashable : Any], SignalInput<()>)>?
		func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable: Any], withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
			let (input, _) = Signal<()>.create { s in s.subscribeWhile { r in completionHandler(); return false } }
			handleRemoteNotificationResponseInfoAction!.send(value: (identifier, userInfo, responseInfo, input))
		}
		
		var didFailToContinueUserActivity: SignalInput<(String, Error)>?
		func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
			didFailToContinueUserActivity!.send(value: (userActivityType, error))
		}
		
		var handleWatchKitExtensionRequest: SignalInput<([AnyHashable: Any]?, SignalInput<[AnyHashable: Any]?>)>?
		func application(_ application: UIApplication, handleWatchKitExtensionRequest userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Void) {
			let (input, _) = Signal<[AnyHashable: Any]?>.create { s in s.subscribeWhile { r in reply(r.value ?? nil); return false } }
			handleWatchKitExtensionRequest!.send(value: (userInfo, input))
		}
		
		var shouldRequestHealthAuthorization: (() -> Void)?
		func applicationShouldRequestHealthAuthorization(_ application: UIApplication) {
			shouldRequestHealthAuthorization!()
		}
		
		var willContinueUserActivity: ((String) -> Bool)?
		func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
			return willContinueUserActivity!(userActivityType)
		}
		
		var continueUserActivity: ((NSUserActivity, SignalInput<[Any]?>) -> Bool)?
		func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
			let (input, _) = Signal<[Any]?>.create { s in s.subscribeWhile { r in restorationHandler(r.value ?? nil); return false } }
			return continueUserActivity!(userActivity, input)
		}
		
		var didUpdate: ((NSUserActivity) -> Void)?
		func application(_ application: UIApplication, didUpdate userActivity: NSUserActivity) {
			didUpdate!(userActivity)
		}
		
		var shouldSaveApplicationState: ((NSCoder) -> Bool)?
		func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
			return shouldSaveApplicationState!(coder)
		}
		
		var shouldRestoreApplicationState: ((NSCoder) -> Bool)?
		func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
			return shouldRestoreApplicationState!(coder)
		}
		
		var viewControllerWithRestorationPath: (([Any], NSCoder) -> UIViewController?)?
		func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? {
			return viewControllerWithRestorationPath!(identifierComponents, coder)
		}
		
		var open: ((URL, [UIApplicationOpenURLOptionsKey: Any]) -> Bool)?
		func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
			return open!(url, options)
		}
		
		var shouldAllowExtensionPointIdentifier: ((UIApplicationExtensionPointIdentifier) -> Bool)?
		func application(_ application: UIApplication, shouldAllowExtensionPointIdentifier extensionPointIdentifier: UIApplicationExtensionPointIdentifier) -> Bool {
			return shouldAllowExtensionPointIdentifier!(extensionPointIdentifier)
		}
		
		var performAction: SignalInput<(UIApplicationShortcutItem, SignalInput<Bool>)>?
		func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
			let (input, _) = Signal<Bool>.create { s in s.subscribeWhile { r in completionHandler(r.value ?? false); return false } }
			performAction!.send(value: (shortcutItem, input))
		}
	}
}

extension BindingName where Binding: ApplicationBinding {
	// You can easily convert the `Binding` cases to `BindingName` using the following Xcode-style regex:
	// Replace: case ([^\(]+)\((.+)\)$
	// With:    static var $1: BindingName<$2, Binding> { return BindingName<$2, Binding>({ v in .applicationBinding(Application.Binding.$1(v)) }) }
	static var ignoreInteractionEvents: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .applicationBinding(Application.Binding.ignoreInteractionEvents(v)) }) }
	static var supportShakeToEdit: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .applicationBinding(Application.Binding.supportShakeToEdit(v)) }) }
	static var isIdleTimerDisabled: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .applicationBinding(Application.Binding.isIdleTimerDisabled(v)) }) }
	static var shortcutItems: BindingName<DynamicValue<[UIApplicationShortcutItem]?>, Binding> { return BindingName<DynamicValue<[UIApplicationShortcutItem]?>, Binding>({ v in .applicationBinding(Application.Binding.shortcutItems(v)) }) }
	static var isNetworkActivityIndicatorVisible: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .applicationBinding(Application.Binding.isNetworkActivityIndicatorVisible(v)) }) }
	static var applicationIconBadgeNumber: BindingName<DynamicValue<Int>, Binding> { return BindingName<DynamicValue<Int>, Binding>({ v in .applicationBinding(Application.Binding.applicationIconBadgeNumber(v)) }) }
	static var statusBarStyle: BindingName<DynamicValue<UIStatusBarStyle>, Binding> { return BindingName<DynamicValue<UIStatusBarStyle>, Binding>({ v in .applicationBinding(Application.Binding.statusBarStyle(v)) }) }
	static var window: BindingName<DynamicValue<WindowConvertible?>, Binding> { return BindingName<DynamicValue<WindowConvertible?>, Binding>({ v in .applicationBinding(Application.Binding.window(v)) }) }
	static var additionalWindows: BindingName<DynamicValue<[WindowConvertible]>, Binding> { return BindingName<DynamicValue<[WindowConvertible]>, Binding>({ v in .applicationBinding(Application.Binding.additionalWindows(v)) }) }
	static var didBecomeActive: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.didBecomeActive(v)) }) }
	static var willResignActive: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.willResignActive(v)) }) }
	static var didEnterBackground: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.didEnterBackground(v)) }) }
	static var willEnterForeground: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.willEnterForeground(v)) }) }
	static var protectedDataWillBecomeUnavailable: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.protectedDataWillBecomeUnavailable(v)) }) }
	static var protectedDataDidBecomeAvailable: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.protectedDataDidBecomeAvailable(v)) }) }
	static var didReceiveMemoryWarning: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.didReceiveMemoryWarning(v)) }) }
	static var significantTimeChange: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .applicationBinding(Application.Binding.significantTimeChange(v)) }) }
	static var performFetch: BindingName<SignalInput<SignalInput<UIBackgroundFetchResult>>, Binding> { return BindingName<SignalInput<SignalInput<UIBackgroundFetchResult>>, Binding>({ v in .applicationBinding(Application.Binding.performFetch(v)) }) }
	static var handleEventsForBackgroundURLSession: BindingName<SignalInput<(String, SignalInput<()>)>, Binding> { return BindingName<SignalInput<(String, SignalInput<()>)>, Binding>({ v in .applicationBinding(Application.Binding.handleEventsForBackgroundURLSession(v)) }) }
	@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var registerUserNotificationSettings: BindingName<Signal<UIUserNotificationSettings>, Binding> { return BindingName<Signal<UIUserNotificationSettings>, Binding>({ v in .applicationBinding(Application.Binding.registerUserNotificationSettings(v)) }) }
	static var registerForRemoteNotifications: BindingName<Signal<Bool>, Binding> { return BindingName<Signal<Bool>, Binding>({ v in .applicationBinding(Application.Binding.registerForRemoteNotifications(v)) }) }
	@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var didRegisterUserNotifications: BindingName<SignalInput<UIUserNotificationSettings>, Binding> { return BindingName<SignalInput<UIUserNotificationSettings>, Binding>({ v in .applicationBinding(Application.Binding.didRegisterUserNotifications(v)) }) }
	static var didRegisterRemoteNotifications: BindingName<SignalInput<Result<Data>>, Binding> { return BindingName<SignalInput<Result<Data>>, Binding>({ v in .applicationBinding(Application.Binding.didRegisterRemoteNotifications(v)) }) }
	@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var didReceiveLocalNotification: BindingName<SignalInput<UILocalNotification>, Binding> { return BindingName<SignalInput<UILocalNotification>, Binding>({ v in .applicationBinding(Application.Binding.didReceiveLocalNotification(v)) }) }
	static var didReceiveRemoteNotification: BindingName<SignalInput<([AnyHashable: Any], SignalInput<UIBackgroundFetchResult>)>, Binding> { return BindingName<SignalInput<([AnyHashable: Any], SignalInput<UIBackgroundFetchResult>)>, Binding>({ v in .applicationBinding(Application.Binding.didReceiveRemoteNotification(v)) }) }
	@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var handleLocalNotificationAction: BindingName<SignalInput<(String?, UILocalNotification, SignalInput<()>)>, Binding> { return BindingName<SignalInput<(String?, UILocalNotification, SignalInput<()>)>, Binding>({ v in .applicationBinding(Application.Binding.handleLocalNotificationAction(v)) }) }
	@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var handleRemoteNotificationAction: BindingName<SignalInput<(String?, [AnyHashable : Any], SignalInput<()>)>, Binding> { return BindingName<SignalInput<(String?, [AnyHashable : Any], SignalInput<()>)>, Binding>({ v in .applicationBinding(Application.Binding.handleRemoteNotificationAction(v)) }) }
	@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var handleLocalNotificationResponseInfoAction: BindingName<SignalInput<(String?, UILocalNotification, [AnyHashable : Any], SignalInput<()>)>, Binding> { return BindingName<SignalInput<(String?, UILocalNotification, [AnyHashable : Any], SignalInput<()>)>, Binding>({ v in .applicationBinding(Application.Binding.handleLocalNotificationResponseInfoAction(v)) }) }
	@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's UNNotificationSettings")
	static var handleRemoteNotificationResponseInfoAction: BindingName<SignalInput<(String?, [AnyHashable : Any], [AnyHashable : Any], SignalInput<()>)>, Binding> { return BindingName<SignalInput<(String?, [AnyHashable : Any], [AnyHashable : Any], SignalInput<()>)>, Binding>({ v in .applicationBinding(Application.Binding.handleRemoteNotificationResponseInfoAction(v)) }) }
	static var didFailToContinueUserActivity: BindingName<SignalInput<(String, Error)>, Binding> { return BindingName<SignalInput<(String, Error)>, Binding>({ v in .applicationBinding(Application.Binding.didFailToContinueUserActivity(v)) }) }
	static var performAction: BindingName<SignalInput<(UIApplicationShortcutItem, SignalInput<Bool>)>, Binding> { return BindingName<SignalInput<(UIApplicationShortcutItem, SignalInput<Bool>)>, Binding>({ v in .applicationBinding(Application.Binding.performAction(v)) }) }
	static var handleWatchKitExtensionRequest: BindingName<SignalInput<([AnyHashable: Any]?, SignalInput<[AnyHashable: Any]?>)>, Binding> { return BindingName<SignalInput<([AnyHashable: Any]?, SignalInput<[AnyHashable: Any]?>)>, Binding>({ v in .applicationBinding(Application.Binding.handleWatchKitExtensionRequest(v)) }) }
	static var willContinueUserActivity: BindingName<(String) -> Bool, Binding> { return BindingName<(String) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.willContinueUserActivity(v)) }) }
	static var continueUserActivity: BindingName<(NSUserActivity, SignalInput<[Any]?>) -> Bool, Binding> { return BindingName<(NSUserActivity, SignalInput<[Any]?>) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.continueUserActivity(v)) }) }
	static var didUpdate: BindingName<(NSUserActivity) -> Void, Binding> { return BindingName<(NSUserActivity) -> Void, Binding>({ v in .applicationBinding(Application.Binding.didUpdate(v)) }) }
	static var willFinishLaunching: BindingName<([UIApplicationLaunchOptionsKey: Any]?) -> Bool, Binding> { return BindingName<([UIApplicationLaunchOptionsKey: Any]?) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.willFinishLaunching(v)) }) }
	static var didFinishLaunching: BindingName<([UIApplicationLaunchOptionsKey: Any]?) -> Bool, Binding> { return BindingName<([UIApplicationLaunchOptionsKey: Any]?) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.didFinishLaunching(v)) }) }
	static var willEncodeRestorableState: BindingName<(NSKeyedArchiver) -> Void, Binding> { return BindingName<(NSKeyedArchiver) -> Void, Binding>({ v in .applicationBinding(Application.Binding.willEncodeRestorableState(v)) }) }
	static var didDecodeRestorableState: BindingName<(NSKeyedUnarchiver) -> Void, Binding> { return BindingName<(NSKeyedUnarchiver) -> Void, Binding>({ v in .applicationBinding(Application.Binding.didDecodeRestorableState(v)) }) }
	static var willTerminate: BindingName<() -> Void, Binding> { return BindingName<() -> Void, Binding>({ v in .applicationBinding(Application.Binding.willTerminate(v)) }) }
	static var shouldSaveApplicationState: BindingName<(_ coder: NSCoder) -> Bool, Binding> { return BindingName<(_ coder: NSCoder) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.shouldSaveApplicationState(v)) }) }
	static var shouldRestoreApplicationState: BindingName<(_ coder: NSCoder) -> Bool, Binding> { return BindingName<(_ coder: NSCoder) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.shouldRestoreApplicationState(v)) }) }
	static var viewControllerWithRestorationPath: BindingName<(_ path: [Any], _ coder: NSCoder) -> UIViewController, Binding> { return BindingName<(_ path: [Any], _ coder: NSCoder) -> UIViewController, Binding>({ v in .applicationBinding(Application.Binding.viewControllerWithRestorationPath(v)) }) }
	static var open: BindingName<(_ url: URL, _ options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool, Binding> { return BindingName<(_ url: URL, _ options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.open(v)) }) }
	static var shouldAllowExtensionPointIdentifier: BindingName<(UIApplicationExtensionPointIdentifier) -> Bool, Binding> { return BindingName<(UIApplicationExtensionPointIdentifier) -> Bool, Binding>({ v in .applicationBinding(Application.Binding.shouldAllowExtensionPointIdentifier(v)) }) }
	static var shouldRequestHealthAuthorization: BindingName<() -> Void, Binding> { return BindingName<() -> Void, Binding>({ v in .applicationBinding(Application.Binding.shouldRequestHealthAuthorization(v)) }) }
}

protocol ApplicationBinding: BaseBinding {
	static func applicationBinding(_ binding: Application.Binding) -> Self
}
extension ApplicationBinding {
	static func baseBinding(_ binding: BaseBinder.Binding) -> Self {
		return applicationBinding(.inheritedBinding(binding))
	}
}

// MARK: ### CwlViewController.swift ###

class ViewController: ConstructingBinder, ViewControllerConvertible {
	typealias Instance = UIViewController
	typealias Inherited = BaseBinder
	
	var state: ConstructingBinderState<Instance, Binding>
	required init(state: ConstructingBinderState<Instance, Binding>) {
		self.state = state
	}
	static func bindingToInherited(_ binding: Binding) -> Inherited.Binding? {
		if case .inheritedBinding(let s) = binding { return s } else { return nil }
	}
	var uiViewController: Instance { return instance() }
	
	enum Binding: ViewControllerBinding {
		typealias EnclosingBinder = ViewController
		static func viewControllerBinding(_ binding: Binding) -> Binding { return binding }
		case inheritedBinding(Inherited.Binding)
		
		//	0. Static bindings are applied at construction and are subsequently immutable.
		case navigationItem(StaticValue<NavigationItem>)
		
		// 1. Value bindings may be applied at construction and may subsequently change.
		case view(DynamicValue<ViewConvertible>)
		@available(iOS, introduced: 7.0, deprecated: 11.0, message: "This property exists to access layout guides prior to iOS 11. On iOS 11 and later, use .layout on the .view")
		case layout(DynamicValue<Layout>)
		case title(DynamicValue<String>)
		case preferredContentSize(DynamicValue<CGSize>)
		case modalPresentationStyle(DynamicValue<UIModalPresentationStyle>)
		case modalTransitionStyle(DynamicValue<UIModalTransitionStyle>)
		case isModalInPopover(DynamicValue<Bool>)
		case definesPresentationContext(DynamicValue<Bool>)
		case providesPresentationContextTransitionStyle(DynamicValue<Bool>)
		case transitioningDelegate(DynamicValue<UIViewControllerTransitioningDelegate>)
		case edgesForExtendedLayout(DynamicValue<UIRectEdge>)
		case extendedLayoutIncludesOpaqueBars(DynamicValue<Bool>)
		case automaticallyAdjustsScrollViewInsets(DynamicValue<Bool>)
		case restorationIdentifier(DynamicValue<String?>)
		case restorationClass(DynamicValue<UIViewControllerRestoration.Type?>)
		case modalPresentationCapturesStatusBarAppearance(DynamicValue<Bool>)
		case hidesBottomBarWhenPushed(DynamicValue<Bool>)
		case toolbarItems(DynamicValue<SetOrAnimate<[BarButtonItemConvertible]>>)
		case tabBarItem(DynamicValue<TabBarItemConvertible>)
		case isEditing(Signal<SetOrAnimate<Bool>>)
		
		// 2. Signal bindings are performed on the object after construction.
		case present(Signal<ModalPresentation>)
		
		// 3. Action bindings are triggered by the object after construction.
		case traitCollectionDidChange(SignalInput<(previous: UITraitCollection?, new: UITraitCollection)>)
		case willAppear(SignalInput<Bool>)
		case didAppear(SignalInput<Bool>)
		case didDisappear(SignalInput<Bool>)
		case willDisappear(SignalInput<Bool>)
		
		// 4. Delegate bindings require synchronous evaluation within the object's context.
		case loadView(() -> ViewConvertible)
		case didReceiveMemoryWarning(() -> Void)
	}
	
	struct Preparer: ConstructingPreparer {
		typealias EnclosingBinder = ViewController
		var linkedPreparer = Inherited.Preparer()
		
		func constructStorage() -> EnclosingBinder.Storage { return Storage() }
		func constructInstance(subclass: EnclosingBinder.Instance.Type) -> EnclosingBinder.Instance { return subclass.init(nibName: nil, bundle: nil) }
		
		init() {}
		
		var view: InitialSubsequent<ViewConvertible>?
		var loadView: (() -> ViewConvertible)?
		
		mutating func prepareBinding(_ binding: Binding) {
			switch binding {
			case .loadView(let x):
				assert(view == nil, "Construct the view using either .loadView or .view, not both.")
				loadView = x
			case .view(let x):
				assert(loadView == nil, "Construct the view using either .loadView or .view, not both.")
				view = x.initialSubsequent()
			case .inheritedBinding(let preceeding): linkedPreparer.prepareBinding(preceeding)
			default: break
			}
		}
		
		mutating func prepareInstance(_ instance: Instance, storage: Storage) {
			// The loadView function needs to be ready in case one of the bindings triggers a view load.
			if let v = view?.initial() {
				storage.view = v
				instance.setBinderStorage(storage)
			} else if let lv = loadView {
				storage.viewConstructor = lv
				instance.setBinderStorage(storage)
			}
		}
		
		func applyBinding(_ binding: Binding, instance: Instance, storage: Storage) -> Cancellable? {
			switch binding {
			case .loadView: return nil
			case .view:
				return view?.subsequent.flatMap { $0.apply(instance, storage) { i, s, v in
					storage.view = v
					if i.isViewLoaded {
						i.view = v.uiView
					}
				} }
			case .layout(let x): return x.apply(instance, storage) { i, s, v in i.applyLayout(v) }
			case .title(let x): return x.apply(instance, storage) { i, s, v in i.title = v }
			case .preferredContentSize(let x): return x.apply(instance, storage) { i, s, v in i.preferredContentSize = v }
			case .modalPresentationStyle(let x): return x.apply(instance, storage) { i, s, v in i.modalPresentationStyle = v }
			case .modalTransitionStyle(let x): return x.apply(instance, storage) { i, s, v in i.modalTransitionStyle = v }
			case .isModalInPopover(let x): return x.apply(instance, storage) { i, s, v in i.isModalInPopover = v }
			case .definesPresentationContext(let x): return x.apply(instance, storage) { i, s, v in i.definesPresentationContext = v }
			case .providesPresentationContextTransitionStyle(let x): return x.apply(instance, storage) { i, s, v in i.providesPresentationContextTransitionStyle = v }
			case .transitioningDelegate(let x): return x.apply(instance, storage) { i, s, v in i.transitioningDelegate = v }
			case .edgesForExtendedLayout(let x): return x.apply(instance, storage) { i, s, v in i.edgesForExtendedLayout = v }
			case .extendedLayoutIncludesOpaqueBars(let x): return x.apply(instance, storage) { i, s, v in i.extendedLayoutIncludesOpaqueBars = v }
			case .automaticallyAdjustsScrollViewInsets(let x):
				return x.apply(instance, storage) { i, s, v in
					if #available(iOS 11, *) {
					} else {
						i.automaticallyAdjustsScrollViewInsets = v
					}
				}
			case .restorationIdentifier(let x): return x.apply(instance, storage) { i, s, v in i.restorationIdentifier = v }
			case .restorationClass(let x): return x.apply(instance, storage) { i, s, v in i.restorationClass = v }
			case .modalPresentationCapturesStatusBarAppearance(let x): return x.apply(instance, storage) { i, s, v in i.modalPresentationCapturesStatusBarAppearance = v }
			case .hidesBottomBarWhenPushed(let x): return x.apply(instance, storage) { i, s, v in i.hidesBottomBarWhenPushed = v }
			case .toolbarItems(let x): return x.apply(instance, storage) { i, s, v in i.setToolbarItems(v.value.map { $0.uiBarButtonItem }, animated: v.isAnimated) }
			case .tabBarItem(let x): return x.apply(instance, storage) { i, s, v in i.tabBarItem = v.uiTabBarItem }
			case .isEditing(let x): return x.apply(instance, storage) { i, s, v in i.setEditing(v.value, animated: v.isAnimated) }
			case .present(let x):
				return x.apply(instance, storage) { i, s, v in
					s.queuedModalPresentations.append(v)
					s.processModalPresentations(viewController: i)
				}
			case .navigationItem(let x):
				x.value.applyBindings(to: instance.navigationItem)
				return nil
			case .traitCollectionDidChange(let x):
				storage.traitCollectionDidChange = x
				return x
			case .willAppear(let x):
				storage.willAppear = x
				return x
			case .didDisappear(let x):
				storage.didDisappear = x
				return x
			case .didAppear(let x):
				storage.didAppear = x
				return x
			case .willDisappear(let x):
				storage.willDisappear = x
				return x
			case .didReceiveMemoryWarning(let x):
				storage.didReceiveMemoryWarning = x
				return nil
			case .inheritedBinding(let s): return linkedPreparer.applyBinding(s, instance: (), storage: ())
			}
		}
		
		mutating func finalizeInstance(_ instance: Instance, storage: Storage) -> Cancellable? {
			let cancellable = linkedPreparer.finalizeInstance((), storage: ())
			
			// Send the initial "traitsCollection" once construction is complete.
			if let tcdc = storage.traitCollectionDidChange {
				tcdc.send(value: (previous: nil, new: instance.traitCollection))
			}
			return cancellable
		}
	}
	
	class Storage: ObjectBinderStorage {
		var traitCollectionDidChange: SignalInput<(previous: UITraitCollection?, new: UITraitCollection)>?
		var didDisappear: SignalInput<Bool>?
		var willAppear: SignalInput<Bool>?
		var willDisappear: SignalInput<Bool>?
		var didAppear: SignalInput<Bool>?
		var queuedModalPresentations: [ModalPresentation] = []
		var presentationInProgress: Bool = false
		var view: ViewConvertible?
		var viewConstructor: (() -> ViewConvertible?)?
		var didReceiveMemoryWarning: (() -> ())?
		
		override var inUse: Bool {
			return super.inUse || view != nil || viewConstructor != nil || didReceiveMemoryWarning != nil
		}
		
		private static var isSwizzled: Bool = false
		private static let ensureSwizzled: () = {
			if isSwizzled {
				assertionFailure("This line should be unreachable")
				return
			}
			
			let loadViewSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.loadView))!
			let loadViewDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledLoadView))!
			method_exchangeImplementations(loadViewSource, loadViewDestination)
			
			let traitCollectionDidChangeSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.traitCollectionDidChange(_:)))!
			let traitCollectionDidChangeDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledTraitCollectionDidChange(_:)))!
			method_exchangeImplementations(traitCollectionDidChangeSource, traitCollectionDidChangeDestination)
			
			let willAppearSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.viewWillAppear(_:)))!
			let willAppearDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledViewWillAppear(_:)))!
			method_exchangeImplementations(willAppearSource, willAppearDestination)
			
			let didDisappearSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.viewDidDisappear(_:)))!
			let didDisappearDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledViewDidDisappear(_:)))!
			method_exchangeImplementations(didDisappearSource, didDisappearDestination)
			
			let didAppearSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.viewDidAppear(_:)))!
			let didAppearDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledViewDidAppear(_:)))!
			method_exchangeImplementations(didAppearSource, didAppearDestination)
			
			let willDisappearSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.viewWillDisappear(_:)))!
			let willDisappearDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledViewWillDisappear(_:)))!
			method_exchangeImplementations(willDisappearSource, willDisappearDestination)
			
			let didReceiveMemoryWarningSource = class_getInstanceMethod(UIViewController.self, #selector(UIViewController.didReceiveMemoryWarning))!
			let didReceiveMemoryWarningDestination = class_getInstanceMethod(ViewController.Storage.self, #selector(ViewController.Storage.swizzledDidReceiveMemoryWarning))!
			method_exchangeImplementations(didReceiveMemoryWarningSource, didReceiveMemoryWarningDestination)
			
			isSwizzled = true
		}()
		
		override init() {
			ViewController.Storage.ensureSwizzled
			super.init()
		}
		
		func processModalPresentations(viewController: UIViewController) {
			if presentationInProgress {
				return
			}
			if let mp = queuedModalPresentations.first {
				if let vc = mp.viewController {
					guard viewController.view.window != nil else {
						presentationInProgress = false
						return
					}
					presentationInProgress = true
					viewController.present(vc.uiViewController, animated: mp.animated) {
						mp.completion?.send(value: ())
						self.queuedModalPresentations.removeFirst()
						self.presentationInProgress = false
						self.processModalPresentations(viewController: viewController)
					}
				} else {
					presentationInProgress = true
					if let vc = viewController.presentedViewController, !vc.isBeingDismissed {
						vc.dismiss(animated: mp.animated, completion: { () -> Void in
							mp.completion?.send(value: ())
							self.queuedModalPresentations.removeFirst()
							self.presentationInProgress = false
							self.processModalPresentations(viewController: viewController)
						})
					} else {
						mp.completion?.send(value: ())
						self.queuedModalPresentations.removeFirst()
						self.presentationInProgress = false
						self.processModalPresentations(viewController: viewController)
					}
				}
			}
		}
		
		func traitCollectionDidChange(_ previous: UITraitCollection?, _ new: UITraitCollection) {
			traitCollectionDidChange?.send(value: (previous: previous, new: new))
		}
		
		func viewWillAppear(controller: UIViewController, animated: Bool) {
			willAppear?.send(value: animated)
		}
		
		func viewDidDisappear(controller: UIViewController, animated: Bool) {
			didDisappear?.send(value: animated)
		}
		
		func viewDidAppear(controller: UIViewController, animated: Bool) {
			didAppear?.send(value: animated)
		}
		
		func viewWillDisappear(controller: UIViewController, animated: Bool) {
			willDisappear?.send(value: animated)
		}
		
		func controllerDidReceiveMemoryWarning(controller: UIViewController) {
			didReceiveMemoryWarning?()
			
			if viewConstructor != nil, let view = controller.viewIfLoaded, view.window == nil {
				controller.view = nil
			}
		}
		
		func loadView(for viewController: UIViewController) -> Bool {
			if let wrapper = view ?? viewConstructor?() {
				viewController.view = wrapper.uiView
				return true
			}
			return false
		}
		
		@objc dynamic private func swizzledLoadView() {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				
				if storage.loadView(for: vc) {
					return
				}
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledLoadView)
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector) -> ()).self)(self, sel)
		}
		
		@objc dynamic private func swizzledTraitCollectionDidChange(_ previous: UITraitCollection?) {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.traitCollectionDidChange(previous, vc.traitCollection)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledTraitCollectionDidChange(_:))
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector, UITraitCollection?) -> ()).self)(self, sel, previous)
		}
		
		@objc dynamic private func swizzledViewWillAppear(_ animated: Bool) {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.viewWillAppear(controller: vc, animated: animated)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledViewWillAppear(_:))
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector, Bool) -> ()).self)(self, sel, animated)
		}
		
		@objc dynamic private func swizzledViewDidDisappear(_ animated: Bool) {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.viewDidDisappear(controller: vc, animated: animated)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledViewDidDisappear(_:))
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector, Bool) -> ()).self)(self, sel, animated)
		}
		
		@objc dynamic private func swizzledViewDidAppear(_ animated: Bool) {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.viewDidAppear(controller: vc, animated: animated)
				
				// Handle any modal presentation that were deferred until adding to the window
				storage.processModalPresentations(viewController: vc)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledViewDidAppear(_:))
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector, Bool) -> ()).self)(self, sel, animated)
		}
		
		@objc dynamic private func swizzledViewWillDisappear(_ animated: Bool) {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.viewWillDisappear(controller: vc, animated: animated)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledViewWillDisappear(_:))
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector, Bool) -> ()).self)(self, sel, animated)
		}
		
		@objc dynamic private func swizzledDidReceiveMemoryWarning() {
			assert(ViewController.Storage.isSwizzled)
			
			// SWIZZLED METHOD WARNING: `self` is an instance of UIViewController, not ViewController.Storage. Don't access any instance members on `self`.
			if let storage = getBinderStorage(type: ViewController.Storage.self) {
				let vc = unsafeBitCast(self, to: UIViewController.self)
				storage.controllerDidReceiveMemoryWarning(controller: vc)
			}
			
			// Relay back to the original implementation
			let sel = #selector(ViewController.Storage.swizzledDidReceiveMemoryWarning)
			let m = class_getMethodImplementation(ViewController.Storage.self, sel)!
			unsafeBitCast(m, to: (@convention(c) (NSObjectProtocol, Selector) -> ()).self)(self, sel)
		}
	}
}

extension BindingName where Binding: ViewControllerBinding {
	// You can easily convert the `Binding` cases to `BindingName` using the following Xcode-style regex:
	// Replace: case ([^\(]+)\((.+)\)$
	// With:    static var $1: BindingName<$2, Binding> { return BindingName<$2, Binding>({ v in .viewControllerBinding(ViewController.Binding.$1(v)) }) }
	static var view: BindingName<DynamicValue<ViewConvertible>, Binding> { return BindingName<DynamicValue<ViewConvertible>, Binding>({ v in .viewControllerBinding(ViewController.Binding.view(v)) }) }
	static var navigationItem: BindingName<StaticValue<NavigationItem>, Binding> { return BindingName<StaticValue<NavigationItem>, Binding>({ v in .viewControllerBinding(ViewController.Binding.navigationItem(v)) }) }
	@available(iOS, introduced: 7.0, deprecated: 11.0, message: "This property exists to access layout guides prior to iOS 11. On iOS 11 and later, use .layout on the .view")
	static var layout: BindingName<DynamicValue<Layout>, Binding> { return BindingName<DynamicValue<Layout>, Binding>({ v in .viewControllerBinding(ViewController.Binding.layout(v)) }) }
	static var title: BindingName<DynamicValue<String>, Binding> { return BindingName<DynamicValue<String>, Binding>({ v in .viewControllerBinding(ViewController.Binding.title(v)) }) }
	static var preferredContentSize: BindingName<DynamicValue<CGSize>, Binding> { return BindingName<DynamicValue<CGSize>, Binding>({ v in .viewControllerBinding(ViewController.Binding.preferredContentSize(v)) }) }
	static var modalPresentationStyle: BindingName<DynamicValue<UIModalPresentationStyle>, Binding> { return BindingName<DynamicValue<UIModalPresentationStyle>, Binding>({ v in .viewControllerBinding(ViewController.Binding.modalPresentationStyle(v)) }) }
	static var modalTransitionStyle: BindingName<DynamicValue<UIModalTransitionStyle>, Binding> { return BindingName<DynamicValue<UIModalTransitionStyle>, Binding>({ v in .viewControllerBinding(ViewController.Binding.modalTransitionStyle(v)) }) }
	static var isModalInPopover: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.isModalInPopover(v)) }) }
	static var definesPresentationContext: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.definesPresentationContext(v)) }) }
	static var providesPresentationContextTransitionStyle: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.providesPresentationContextTransitionStyle(v)) }) }
	static var transitioningDelegate: BindingName<DynamicValue<UIViewControllerTransitioningDelegate>, Binding> { return BindingName<DynamicValue<UIViewControllerTransitioningDelegate>, Binding>({ v in .viewControllerBinding(ViewController.Binding.transitioningDelegate(v)) }) }
	static var edgesForExtendedLayout: BindingName<DynamicValue<UIRectEdge>, Binding> { return BindingName<DynamicValue<UIRectEdge>, Binding>({ v in .viewControllerBinding(ViewController.Binding.edgesForExtendedLayout(v)) }) }
	static var extendedLayoutIncludesOpaqueBars: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.extendedLayoutIncludesOpaqueBars(v)) }) }
	static var automaticallyAdjustsScrollViewInsets: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.automaticallyAdjustsScrollViewInsets(v)) }) }
	static var restorationIdentifier: BindingName<DynamicValue<String?>, Binding> { return BindingName<DynamicValue<String?>, Binding>({ v in .viewControllerBinding(ViewController.Binding.restorationIdentifier(v)) }) }
	static var restorationClass: BindingName<DynamicValue<UIViewControllerRestoration.Type?>, Binding> { return BindingName<DynamicValue<UIViewControllerRestoration.Type?>, Binding>({ v in .viewControllerBinding(ViewController.Binding.restorationClass(v)) }) }
	static var modalPresentationCapturesStatusBarAppearance: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.modalPresentationCapturesStatusBarAppearance(v)) }) }
	static var hidesBottomBarWhenPushed: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.hidesBottomBarWhenPushed(v)) }) }
	static var toolbarItems: BindingName<DynamicValue<SetOrAnimate<[BarButtonItemConvertible]>>, Binding> { return BindingName<DynamicValue<SetOrAnimate<[BarButtonItemConvertible]>>, Binding>({ v in .viewControllerBinding(ViewController.Binding.toolbarItems(v)) }) }
	static var tabBarItem: BindingName<DynamicValue<TabBarItemConvertible>, Binding> { return BindingName<DynamicValue<TabBarItemConvertible>, Binding>({ v in .viewControllerBinding(ViewController.Binding.tabBarItem(v)) }) }
	static var isEditing: BindingName<Signal<SetOrAnimate<Bool>>, Binding> { return BindingName<Signal<SetOrAnimate<Bool>>, Binding>({ v in .viewControllerBinding(ViewController.Binding.isEditing(v)) }) }
	static var present: BindingName<Signal<ModalPresentation>, Binding> { return BindingName<Signal<ModalPresentation>, Binding>({ v in .viewControllerBinding(ViewController.Binding.present(v)) }) }
	static var traitCollectionDidChange: BindingName<SignalInput<(previous: UITraitCollection?, new: UITraitCollection)>, Binding> { return BindingName<SignalInput<(previous: UITraitCollection?, new: UITraitCollection)>, Binding>({ v in .viewControllerBinding(ViewController.Binding.traitCollectionDidChange(v)) }) }
	static var willAppear: BindingName<SignalInput<Bool>, Binding> { return BindingName<SignalInput<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.willAppear(v)) }) }
	static var didAppear: BindingName<SignalInput<Bool>, Binding> { return BindingName<SignalInput<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.didAppear(v)) }) }
	static var didDisappear: BindingName<SignalInput<Bool>, Binding> { return BindingName<SignalInput<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.didDisappear(v)) }) }
	static var willDisappear: BindingName<SignalInput<Bool>, Binding> { return BindingName<SignalInput<Bool>, Binding>({ v in .viewControllerBinding(ViewController.Binding.willDisappear(v)) }) }
	static var loadView: BindingName<() -> ViewConvertible, Binding> { return BindingName<() -> ViewConvertible, Binding>({ v in .viewControllerBinding(ViewController.Binding.loadView(v)) }) }
}

protocol ViewControllerConvertible {
	var uiViewController: ViewController.Instance { get }
}
extension ViewController.Instance: ViewControllerConvertible {
	var uiViewController: ViewController.Instance { return self }
}

protocol ViewControllerBinding: BaseBinding {
	static func viewControllerBinding(_ binding: ViewController.Binding) -> Self
}
extension ViewControllerBinding {
	static func baseBinding(_ binding: BaseBinder.Binding) -> Self {
		return viewControllerBinding(.inheritedBinding(binding))
	}
}

struct ModalPresentation {
	let viewController: ViewControllerConvertible?
	let animated: Bool
	let completion: SignalInput<()>?
	
	init(_ viewController: ViewControllerConvertible? = nil, animated: Bool = true, completion: SignalInput<()>? = nil) {
		self.viewController = viewController
		self.animated = animated
		self.completion = completion
	}
}

extension SignalInterface {
	func modalPresentation<T>(_ construct: @escaping (T) -> ViewControllerConvertible) -> Signal<ModalPresentation> where OutputValue == Optional<T> {
		return transform { (result, next) in
			switch result {
			case .success(.some(let t)): next.send(value: ModalPresentation(construct(t)))
			case .success: next.send(value: ModalPresentation(nil))
			case .failure(let e): next.send(error: e)
			}
		}
	}
}

// MARK: ### CwlScrollView.swift ###

class ScrollView: ConstructingBinder, ScrollViewConvertible {
	typealias Instance = UIScrollView
	typealias Inherited = View
	
	var state: ConstructingBinderState<Instance, Binding>
	required init(state: ConstructingBinderState<Instance, Binding>) {
		self.state = state
	}
	static func bindingToInherited(_ binding: Binding) -> Inherited.Binding? {
		if case .inheritedBinding(let s) = binding { return s } else { return nil }
	}
	var uiScrollView: Instance { return instance() }
	
	enum Binding: ScrollViewBinding {
		typealias EnclosingBinder = ScrollView
		static func scrollViewBinding(_ binding: Binding) -> Binding { return binding }
		case inheritedBinding(Inherited.Binding)
		
		//	0. Static bindings are applied at construction and are subsequently immutable.
		case panGestureRecognizerStyles(StaticValue<PanGestureRecognizer>)
		case pinchGestureRecognizerStyles(StaticValue<PinchGestureRecognizer>)
		
		// 1. Value bindings may be applied at construction and may subsequently change.
		case contentOffset(DynamicValue<SetOrAnimate<CGPoint>>)
		case contentSize(DynamicValue<CGSize>)
		case contentInset(DynamicValue<UIEdgeInsets>)
		case isScrollEnabled(DynamicValue<Bool>)
		case isDirectionalLockEnabled(DynamicValue<Bool>)
		case scrollsToTop(DynamicValue<Bool>)
		case isPagingEnabled(DynamicValue<Bool>)
		case bounces(DynamicValue<Bool>)
		case alwaysBounceVertical(DynamicValue<Bool>)
		case alwaysBounceHorizontal(DynamicValue<Bool>)
		case canCancelContentTouches(DynamicValue<Bool>)
		case delaysContentTouches(DynamicValue<Bool>)
		case decelerationRate(DynamicValue<CGFloat>)
		case indicatorStyle(DynamicValue<UIScrollViewIndicatorStyle>)
		case scrollIndicatorInsets(DynamicValue<UIEdgeInsets>)
		case showsHorizontalScrollIndicator(DynamicValue<Bool>)
		case showsVerticalScrollIndicator(DynamicValue<Bool>)
		case zoomScale(DynamicValue<CGFloat>)
		case maximumZoomScale(DynamicValue<CGFloat>)
		case minimumZoomScale(DynamicValue<CGFloat>)
		case bouncesZoom(DynamicValue<Bool>)
		@available(iOS 10.0, *) case refreshControl(DynamicValue<UIRefreshControl?>)
		
		// 2. Signal bindings are performed on the object after construction.
		case scrollRectToVisible(Signal<(rect: CGRect, animated: Bool)>)
		case zoom(Signal<(rect: CGRect, animated: Bool)>)
		case flashScrollIndicators(Signal<()>)
		
		// 3. Action bindings are triggered by the object after construction.
		case userDidScroll(SignalInput<CGPoint>)
		case didScroll(SignalInput<CGPoint>)
		case didZoom(SignalInput<CGFloat>)
		case willBeginDragging(SignalInput<CGPoint>)
		case didEndDragging(SignalInput<(CGPoint, Bool)>)
		case didScrollToTop(SignalInput<()>)
		case willBeginDecelerating(SignalInput<()>)
		case didEndDecelerating(SignalInput<CGPoint>)
		case willBeginZooming(SignalInput<CGFloat>)
		case didEndZooming(SignalInput<CGFloat>)
		case didEndScrollingAnimation(SignalInput<CGPoint>)
		
		// 4. Delegate bindings require synchronous evaluation within the object's context.
		case willEndDragging((_ scrollView: UIScrollView, _ velocity: CGPoint, _ targetContentOffset: UnsafeMutablePointer<CGPoint>) -> Void)
		case shouldScrollToTop((_ scrollView: UIScrollView) -> Bool)
		case viewForZooming((_ scrollView: UIScrollView) -> UIView?)
	}
	
	struct Preparer: ConstructingPreparer {
		typealias EnclosingBinder = ScrollView
		var linkedPreparer = Inherited.Preparer()
		
		func constructStorage() -> EnclosingBinder.Storage { return Storage() }
		func constructInstance(subclass: EnclosingBinder.Instance.Type) -> EnclosingBinder.Instance { return subclass.init() }
		
		init() {
			self.init(delegateClass: Delegate.self)
		}
		init<Value>(delegateClass: Value.Type) where Value: Delegate {
			self.delegateClass = delegateClass
		}
		let delegateClass: Delegate.Type
		var possibleDelegate: Delegate? = nil
		mutating func delegate() -> Delegate {
			if let d = possibleDelegate {
				return d
			} else {
				let d = delegateClass.init()
				possibleDelegate = d
				return d
			}
		}
		
		mutating func prepareBinding(_ binding: Binding) {
			switch binding {
			case .userDidScroll(let x):
				let s1 = #selector(UIScrollViewDelegate.scrollViewDidScrollToTop(_:))
				let s2 = #selector(UIScrollViewDelegate.scrollViewDidEndDragging(_:willDecelerate:))
				let s3 = #selector(UIScrollViewDelegate.scrollViewDidEndDecelerating(_:))
				delegate().addSelector(s1).userDidScroll = x
				_ = delegate().addSelector(s2)
				_ = delegate().addSelector(s3)
			case .didScroll(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidScroll(_:))
				delegate().addSelector(s).didScroll = x
			case .didZoom(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidZoom(_:))
				delegate().addSelector(s).didZoom = x
			case .willBeginDragging(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewWillBeginDragging(_:))
				delegate().addSelector(s).willBeginDragging = x
			case .didEndDragging(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidEndDragging(_:willDecelerate:))
				delegate().addSelector(s).didEndDragging = x
			case .didScrollToTop(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidScrollToTop(_:))
				delegate().addSelector(s).didScrollToTop = x
			case .willBeginDecelerating(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewWillBeginDecelerating(_:))
				delegate().addSelector(s).willBeginDecelerating = x
			case .didEndDecelerating(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidEndDecelerating(_:))
				delegate().addSelector(s).didEndDecelerating = x
			case .willBeginZooming(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewWillBeginZooming(_:with:))
				delegate().addSelector(s).willBeginZooming = x
			case .didEndZooming(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidEndZooming(_:with:atScale:))
				delegate().addSelector(s).didEndZooming = x
			case .didEndScrollingAnimation(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation(_:))
				delegate().addSelector(s).didEndScrollingAnimation = x
			case .willEndDragging(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewWillEndDragging(_:withVelocity:targetContentOffset:))
				delegate().addSelector(s).willEndDragging = x
			case .shouldScrollToTop(let x):
				let s = #selector(UIScrollViewDelegate.scrollViewShouldScrollToTop(_:))
				delegate().addSelector(s).shouldScrollToTop = x
			case .viewForZooming(let x):
				let s = #selector(UIScrollViewDelegate.viewForZooming(in:))
				delegate().addSelector(s).forZooming = x
			case .inheritedBinding(let x): linkedPreparer.prepareBinding(x)
			default: break
			}
		}
		
		mutating func prepareInstance(_ instance: Instance, storage: Storage) {
			precondition(instance.delegate == nil, "Conflicting delegate applied to instance")
			storage.dynamicDelegate = possibleDelegate
			if storage.inUse {
				instance.delegate = storage
			}
			
			linkedPreparer.prepareInstance(instance, storage: storage)
		}
		
		func applyBinding(_ binding: Binding, instance: Instance, storage: Storage) -> Cancellable? {
			switch binding {
			case .panGestureRecognizerStyles(let x):
				x.value.applyBindings(to: instance.panGestureRecognizer)
				return nil
			case .pinchGestureRecognizerStyles(let x):
				if let pgr = instance.pinchGestureRecognizer {
					x.value.applyBindings(to: pgr)
				}
				return nil
			case .contentOffset(let x): return x.apply(instance, storage) { i, s, v in i.setContentOffset(v.value, animated: v.isAnimated) }
			case .contentSize(let x): return x.apply(instance, storage) { i, s, v in i.contentSize = v }
			case .contentInset(let x): return x.apply(instance, storage) { i, s, v in i.contentInset = v }
			case .isScrollEnabled(let x): return x.apply(instance, storage) { i, s, v in i.isScrollEnabled = v }
			case .isDirectionalLockEnabled(let x): return x.apply(instance, storage) { i, s, v in i.isDirectionalLockEnabled = v }
			case .scrollsToTop(let x): return x.apply(instance, storage) { i, s, v in i.scrollsToTop = v }
			case .isPagingEnabled(let x): return x.apply(instance, storage) { i, s, v in i.isPagingEnabled = v }
			case .bounces(let x): return x.apply(instance, storage) { i, s, v in i.bounces = v }
			case .alwaysBounceVertical(let x): return x.apply(instance, storage) { i, s, v in i.alwaysBounceVertical = v }
			case .alwaysBounceHorizontal(let x): return x.apply(instance, storage) { i, s, v in i.alwaysBounceHorizontal = v }
			case .canCancelContentTouches(let x): return x.apply(instance, storage) { i, s, v in i.canCancelContentTouches = v }
			case .delaysContentTouches(let x): return x.apply(instance, storage) { i, s, v in i.delaysContentTouches = v }
			case .decelerationRate(let x): return x.apply(instance, storage) { i, s, v in i.decelerationRate = v }
			case .indicatorStyle(let x): return x.apply(instance, storage) { i, s, v in i.indicatorStyle = v }
			case .scrollIndicatorInsets(let x): return x.apply(instance, storage) { i, s, v in i.scrollIndicatorInsets = v }
			case .showsHorizontalScrollIndicator(let x): return x.apply(instance, storage) { i, s, v in i.showsHorizontalScrollIndicator = v }
			case .showsVerticalScrollIndicator(let x): return x.apply(instance, storage) { i, s, v in i.showsVerticalScrollIndicator = v }
			case .zoomScale(let x): return x.apply(instance, storage) { i, s, v in i.zoomScale = v }
			case .maximumZoomScale(let x): return x.apply(instance, storage) { i, s, v in i.maximumZoomScale = v }
			case .minimumZoomScale(let x): return x.apply(instance, storage) { i, s, v in i.minimumZoomScale = v }
			case .bouncesZoom(let x): return x.apply(instance, storage) { i, s, v in i.bouncesZoom = v }
			case .refreshControl(let x):
				return x.apply(instance, storage) { i, s, v in
					if #available(iOS 10.0, *) {
						i.refreshControl = v
					}
				}
			case .scrollRectToVisible(let x): return x.apply(instance, storage) { i, s, v in i.scrollRectToVisible(v.rect, animated: v.animated) }
			case .zoom(let x): return x.apply(instance, storage) { i, s, v in i.zoom(to: v.rect, animated: v.animated) }
			case .flashScrollIndicators(let x): return x.apply(instance, storage) { i, s, v in i.flashScrollIndicators() }
			case .userDidScroll: return nil
			case .didScroll: return nil
			case .didZoom: return nil
			case .willBeginDragging: return nil
			case .didEndDragging: return nil
			case .didScrollToTop: return nil
			case .willBeginDecelerating: return nil
			case .didEndDecelerating: return nil
			case .willBeginZooming: return nil
			case .didEndZooming: return nil
			case .didEndScrollingAnimation: return nil
			case .willEndDragging: return nil
			case .shouldScrollToTop: return nil
			case .viewForZooming: return nil
			case .inheritedBinding(let s): return linkedPreparer.applyBinding(s, instance: instance, storage: storage)
			}
		}
	}
	
	class Storage: View.Storage, UIScrollViewDelegate {}
	
	class Delegate: DynamicDelegate, UIScrollViewDelegate {
		required override init() {
			super.init()
		}
		
		var userDidScroll: SignalInput<CGPoint>?
		
		var didEndDragging: SignalInput<(CGPoint, Bool)>?
		func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
			if !decelerate {
				userDidScroll?.send(value: scrollView.contentOffset)
			}
			didEndDragging?.send(value: (scrollView.contentOffset, decelerate))
		}
		
		var didScrollToTop: SignalInput<()>?
		func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
			userDidScroll?.send(value: scrollView.contentOffset)
			didScrollToTop!.send(value: ())
		}
		
		var didEndDecelerating: SignalInput<CGPoint>?
		func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
			userDidScroll?.send(value: scrollView.contentOffset)
			didEndDecelerating?.send(value: scrollView.contentOffset)
		}
		
		var didScroll: SignalInput<CGPoint>?
		func scrollViewDidScroll(_ scrollView: UIScrollView) {
			didScroll?.send(value: scrollView.contentOffset)
		}
		
		var didZoom: SignalInput<CGFloat>?
		func scrollViewDidZoom(_ scrollView: UIScrollView) {
			didZoom!.send(value: scrollView.zoomScale)
		}
		
		var willBeginDragging: SignalInput<CGPoint>?
		func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
			willBeginDragging!.send(value: scrollView.contentOffset)
		}
		
		var willBeginDecelerating: SignalInput<()>?
		func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
			willBeginDecelerating!.send(value: ())
		}
		
		var willBeginZooming: SignalInput<CGFloat>?
		func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
			willBeginZooming!.send(value: scrollView.contentScaleFactor)
		}
		
		var didEndZooming: SignalInput<CGFloat>?
		func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
			didEndZooming!.send(value: scale)
		}
		
		var didEndScrollingAnimation: SignalInput<CGPoint>?
		func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
			didEndScrollingAnimation!.send(value: scrollView.contentOffset)
		}
		
		var willEndDragging: ((_ scrollView: UIScrollView, _ velocity: CGPoint, _ targetContentOffset: UnsafeMutablePointer<CGPoint>) -> Void)?
		func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
			willEndDragging!(scrollView, velocity, targetContentOffset)
		}
		
		var shouldScrollToTop: ((_ scrollView: UIScrollView) -> Bool)?
		func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
			return shouldScrollToTop!(scrollView)
		}
		
		var forZooming: ((_ scrollView: UIScrollView) -> UIView?)?
		func viewForZooming(in scrollView: UIScrollView) -> UIView? {
			return forZooming!(scrollView)
		}
	}
}

extension BindingName where Binding: ScrollViewBinding {
	// You can easily convert the `Binding` cases to `BindingName` using the following Xcode-style regex:
	// Replace: case ([^\(]+)\((.+)\)$
	// With:    static var $1: BindingName<$2, Binding> { return BindingName<$2, Binding>({ v in .scrollViewBinding(ScrollView.Binding.$1(v)) }) }
	static var panGestureRecognizerStyles: BindingName<StaticValue<PanGestureRecognizer>, Binding> { return BindingName<StaticValue<PanGestureRecognizer>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.panGestureRecognizerStyles(v)) }) }
	static var pinchGestureRecognizerStyles: BindingName<StaticValue<PinchGestureRecognizer>, Binding> { return BindingName<StaticValue<PinchGestureRecognizer>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.pinchGestureRecognizerStyles(v)) }) }
	static var contentOffset: BindingName<DynamicValue<SetOrAnimate<CGPoint>>, Binding> { return BindingName<DynamicValue<SetOrAnimate<CGPoint>>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.contentOffset(v)) }) }
	static var contentSize: BindingName<DynamicValue<CGSize>, Binding> { return BindingName<DynamicValue<CGSize>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.contentSize(v)) }) }
	static var contentInset: BindingName<DynamicValue<UIEdgeInsets>, Binding> { return BindingName<DynamicValue<UIEdgeInsets>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.contentInset(v)) }) }
	static var isScrollEnabled: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.isScrollEnabled(v)) }) }
	static var isDirectionalLockEnabled: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.isDirectionalLockEnabled(v)) }) }
	static var scrollsToTop: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.scrollsToTop(v)) }) }
	static var isPagingEnabled: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.isPagingEnabled(v)) }) }
	static var bounces: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.bounces(v)) }) }
	static var alwaysBounceVertical: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.alwaysBounceVertical(v)) }) }
	static var alwaysBounceHorizontal: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.alwaysBounceHorizontal(v)) }) }
	static var canCancelContentTouches: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.canCancelContentTouches(v)) }) }
	static var delaysContentTouches: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.delaysContentTouches(v)) }) }
	static var decelerationRate: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.decelerationRate(v)) }) }
	static var indicatorStyle: BindingName<DynamicValue<UIScrollViewIndicatorStyle>, Binding> { return BindingName<DynamicValue<UIScrollViewIndicatorStyle>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.indicatorStyle(v)) }) }
	static var scrollIndicatorInsets: BindingName<DynamicValue<UIEdgeInsets>, Binding> { return BindingName<DynamicValue<UIEdgeInsets>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.scrollIndicatorInsets(v)) }) }
	static var showsHorizontalScrollIndicator: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.showsHorizontalScrollIndicator(v)) }) }
	static var showsVerticalScrollIndicator: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.showsVerticalScrollIndicator(v)) }) }
	static var zoomScale: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.zoomScale(v)) }) }
	static var maximumZoomScale: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.maximumZoomScale(v)) }) }
	static var minimumZoomScale: BindingName<DynamicValue<CGFloat>, Binding> { return BindingName<DynamicValue<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.minimumZoomScale(v)) }) }
	static var bouncesZoom: BindingName<DynamicValue<Bool>, Binding> { return BindingName<DynamicValue<Bool>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.bouncesZoom(v)) }) }
	@available(iOS 10.0, *) static var refreshControl: BindingName<DynamicValue<UIRefreshControl?>, Binding> { return BindingName<DynamicValue<UIRefreshControl?>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.refreshControl(v)) }) }
	static var scrollRectToVisible: BindingName<Signal<(rect: CGRect, animated: Bool)>, Binding> { return BindingName<Signal<(rect: CGRect, animated: Bool)>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.scrollRectToVisible(v)) }) }
	static var zoom: BindingName<Signal<(rect: CGRect, animated: Bool)>, Binding> { return BindingName<Signal<(rect: CGRect, animated: Bool)>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.zoom(v)) }) }
	static var flashScrollIndicators: BindingName<Signal<()>, Binding> { return BindingName<Signal<()>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.flashScrollIndicators(v)) }) }
	static var userDidScroll: BindingName<SignalInput<CGPoint>, Binding> { return BindingName<SignalInput<CGPoint>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.userDidScroll(v)) }) }
	static var didScroll: BindingName<SignalInput<CGPoint>, Binding> { return BindingName<SignalInput<CGPoint>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didScroll(v)) }) }
	static var didZoom: BindingName<SignalInput<CGFloat>, Binding> { return BindingName<SignalInput<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didZoom(v)) }) }
	static var willBeginDragging: BindingName<SignalInput<CGPoint>, Binding> { return BindingName<SignalInput<CGPoint>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.willBeginDragging(v)) }) }
	static var didEndDragging: BindingName<SignalInput<(CGPoint, Bool)>, Binding> { return BindingName<SignalInput<(CGPoint, Bool)>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didEndDragging(v)) }) }
	static var didScrollToTop: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didScrollToTop(v)) }) }
	static var willBeginDecelerating: BindingName<SignalInput<()>, Binding> { return BindingName<SignalInput<()>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.willBeginDecelerating(v)) }) }
	static var didEndDecelerating: BindingName<SignalInput<CGPoint>, Binding> { return BindingName<SignalInput<CGPoint>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didEndDecelerating(v)) }) }
	static var willBeginZooming: BindingName<SignalInput<CGFloat>, Binding> { return BindingName<SignalInput<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.willBeginZooming(v)) }) }
	static var didEndZooming: BindingName<SignalInput<CGFloat>, Binding> { return BindingName<SignalInput<CGFloat>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didEndZooming(v)) }) }
	static var didEndScrollingAnimation: BindingName<SignalInput<CGPoint>, Binding> { return BindingName<SignalInput<CGPoint>, Binding>({ v in .scrollViewBinding(ScrollView.Binding.didEndScrollingAnimation(v)) }) }
	static var willEndDragging: BindingName<(_ scrollView: UIScrollView, _ velocity: CGPoint, _ targetContentOffset: UnsafeMutablePointer<CGPoint>) -> Void, Binding> { return BindingName<(_ scrollView: UIScrollView, _ velocity: CGPoint, _ targetContentOffset: UnsafeMutablePointer<CGPoint>) -> Void, Binding>({ v in .scrollViewBinding(ScrollView.Binding.willEndDragging(v)) }) }
	static var shouldScrollToTop: BindingName<(_ scrollView: UIScrollView) -> Bool, Binding> { return BindingName<(_ scrollView: UIScrollView) -> Bool, Binding>({ v in .scrollViewBinding(ScrollView.Binding.shouldScrollToTop(v)) }) }
	static var viewForZooming: BindingName<(_ scrollView: UIScrollView) -> UIView?, Binding> { return BindingName<(_ scrollView: UIScrollView) -> UIView?, Binding>({ v in .scrollViewBinding(ScrollView.Binding.viewForZooming(v)) }) }
}

protocol ScrollViewConvertible: ViewConvertible {
	var uiScrollView: ScrollView.Instance { get }
}
extension ScrollViewConvertible {
	var uiView: View.Instance { return uiScrollView }
}
extension ScrollView.Instance: ScrollViewConvertible {
	var uiScrollView: ScrollView.Instance { return self }
}

protocol ScrollViewBinding: ViewBinding {
	static func scrollViewBinding(_ binding: ScrollView.Binding) -> Self
}
extension ScrollViewBinding {
	static func viewBinding(_ binding: View.Binding) -> Self {
		return scrollViewBinding(.inheritedBinding(binding))
	}
}
